This site best when viewed with a modern standards-compliant browser. We recommend Firefox Get Firefox!.

Linux-HA project logo
Providing Open Source High-Availability Software for Linux and other OSes since 1999.

USA Flag UK Flag

Japanese Flag

Homepage

About Us

Contact Us

Legal Info

How To Contribute

Security Issues

This web page is no longer maintained. Information presented here exists only to avoid breaking historical links.
The Project stays maintained, and lives on: see the Linux-HA Reference Documentation.
To get rid of this notice, you may want to browse the old wiki instead.

1 February 2010 Hearbeat 3.0.2 released see the Release Notes

18 January 2009 Pacemaker 1.0.7 released see the Release Notes

16 November 2009 LINBIT new Heartbeat Steward see the Announcement

Last site update:
2017-12-15 01:16:10

C Coding standards

  1. All code shall be readable. Clarity is a very great virtue. If you want to optimize your code, optimize for the readers brain first.
  2. All code will compile without any warnings on Linux. This is sometimes hard. It is not negotiable. Get help if you get stuck trying to eliminate warnings. Don't waste a lot of time on it - there are people on the project who are very good at this.

  3. All if, for, while, and similar statements must be fully bracketed. There is no reason to make exceptions for this. Automatically following this practice automatically makes a whole class of errors completely impossible.

  4. All code will be indented with tabs with 8-character definitions, not spaces. Have a look at linux/Documentation/CodingStyle for a good read...

  5. All lines should be shorter than 81 characters (preferably 78 characters) Even string constants can be made to do this.

  6. All names for function bodies start at the beginning of a line.

  7. The opening and closing brackets for function bodies start at the beginning of a line.

  8. White space is generally a good thing.

    • if ( is preferable to if(

    • foo, bar is preferable to foo,bar

  9. Follow normal, portable C conventions.
  10. In if statements which check for errors, normally put the error case in the then branch, not the else branch. This is because it is common for error returns to print something out, then return - a short piece of code. In this case, you do not then need to make your code more and more deeply indented, therefore harder to follow. Even if you don't return, but have an }else{ case, this else case will come only a few lines after the if condition, which will make it easier to figure out under what circumstances the }else{ case is reached. Therefore more clear. If you do it the other way around, then your else case (error condition handling) will be many lines away, making it harder to figure out under what conditions the error case is reached. Therefore, this way is less clear. See the first rule.

    If you need help, pipe your code through indent -kr -i8

  11. When the code does weird things, or subtle, non-obvious things, comments that explain things are good. Don't hesistate to put details for these cases. If it wasn't obvious to you when you first wrote it, it won't be obvious to the casual reader either.

    • Code which doesn't do weird things is even better.

  12. Use the standard functions (plumbing) provided by the project. These include PILS, logging, simple IPC, longclock_t, temp file creation, process tracking, and

    probably other things I ought to include here ;-) Among other things, this means use the logging functions, not printf, et al.

  13. Use the autoconf variables for computing pathnames. Add new ones if needed.
  14. Everything should run on all our platforms unless there is some inherently good reason why it should be platform-specific.
    • getopt_long() is not available on many platforms
    • // style comments from C++ should not be used

    • declarations must go at the beginning of {} blocks, not in the middle.

  15. Libraries should go under one of the /lib directories. Add new ones if you need to.
  16. Plugins should go under subdirectories of /lib/plugins. Add new ones if you need to.
  17. Security is importants in design and in code.
    • Ask for help when you have questions.

      Avoid strcpy, strcat, strlen, etc. Use strncpy, strncat, strnlen, etc. Design interfaces to pass size of buffers for return strings, or malloc space for return results.

      {X} Do we prefer caller allocated, or callee allocated?

      • I have a rule but not a strict one. What I've typically done is when the thing being returned is the primary return result, I let the procedure-being-called allocate the space. Exceptions to this are when there's some good reason to think the caller will need that space for something else - like to append something else to it. For example, in the netstrings code, the caller specifically computes the total space for the entire return result, and many subprocedures are called to append to that result. This is a reasonably sensible approach for this task, because it avoids many separate allocations, appends, and possible reallocs, and heartbeat can spend much of its time here. But, as I said, I consider it an exception, not the rule. Another general rule: If an object is allocated/newed/created by one function, and used only until that function returns, then the allocation and the freeing should occur in that same function, so that code readers can easily audit the code for memory leaks.

Generally Good Guidelines

  1. Check parameters passed into functions. Assume your caller is an idiot. If the data you're getting comes from a human this goes 10 times over. If the data you're getting comes from the network, assume your caller is actively hostile.

  2. Always log errors. Only if they are logged can we ever figure out what happened. The log is how we debug things all over the world from all kinds of users. Log all the

    this can't happen conditions, bad input, bad logic, WTF errors, etc. It will make your code longer. Do it anyway.

  3. Always use the right logging mechanism for logging. This is cl_log() for most things, and PILCallLog() for plugins.

  4. Check computed results withing a function when the logic is long or complex.
  5. Avoid threads. Avoid blocking. Use ipc.h and g_mainloop() for client-server things.

  6. Avoid C++ for the most critical of tasks. Everything we do must be free of all memory leaks.
  7. Avoid unnecessary mallocs, and be careful about memory you do malloc().

  8. Write audit code which verifies the integrity of important things.
  9. Spend time putting in debug statements you can turn on at run time. Make them meaningful and unique when read in a log.
  10. Read the DevCorner/LoggingConventions for more information about logging and debug output.

  11. Add to the standard functions for the project when appropriate.
  12. When you borrow code from another open source project for this project, always credit the source, and doublecheck the copyright and license, and run it by

    AlanRobertson, who will run it by lawyers if necessary. Make sure you say exactly where you got it from (url, date, time) and what license it was made available under. Ask for help in understanding the license issues. Furthermore, it is necessary to have legal releases for each contributor to the project. AlanRobertson will take care of those, but they're necessary. Check with him for more detail.