CODING_STYLE revision 8d0e0ddda6501479eb69164687c83c1a7667b33a
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy- 8ch indent, no tabs
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy- Variables and functions *must* be static, unless they have a
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy prototype, and are supposed to be exported.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy- structs in MixedCase (with exceptions, such as public API structs),
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy variables + functions in lower_case.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy- The destructors always unregister the object from the next bigger
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy object, not the other way around
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy- To minimize strict aliasing violations, we prefer unions over casting
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy- For robustness reasons, destructors should be able to destruct
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy half-initialized objects, too
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy- Error codes are returned as negative Exxx. i.e. return -EINVAL. There
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy are some exceptions: for constructors, it is OK to return NULL on
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy OOM. For lookup functions, NULL is fine too for "not found".
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy Be strict with this. When you write a function that can fail due to
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy more than one cause, it *really* should have "int" as return value
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy for the error code.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy- Don't bother with error checking whether writing to stdout/stderr
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy worked.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy- Do not log errors from "library" code, only do so from "main
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy program" code. (With one exception: it's OK to log with DEBUG level
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy from any code, with the exception of maybe inner loops).
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy- Always check OOM. There's no excuse. In program code, you can use
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy "log_oom()" for then printing a short message, but not in "library" code.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy- Do not issue NSS requests (that includes user name and host name
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy lookups) from PID 1 as this might trigger deadlocks when those
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy lookups involve synchronously talking to services that we would need
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy to start up
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy- Don't synchronously talk to any other service from PID 1, due to
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy risk of deadlocks
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy- Avoid fixed sized string buffers, unless you really know the maximum
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy size and that maximum size is small. They are a source of errors,
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy since they possibly result in truncated strings. Often it is nicer
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy to use dynamic memory, alloca() or VLAs. If you do allocate fixed
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy size strings on the stack, then it's probably only OK if you either
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy use a maximum size such as LINE_MAX, or count in detail the maximum
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy size a string can have. (DECIMAL_STR_MAX and DECIMAL_STR_WIDTH
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy macros are your friends for this!)
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy Or in other words, if you use "char buf[256]" then you are likely
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy doing something wrong!
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy- Stay uniform. For example, always use "usec_t" for time
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy values. Don't usec mix msec, and usec and whatnot.
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy- Make use of _cleanup_free_ and friends. It makes your code much
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy nicer to read!
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy- Be exceptionally careful when formatting and parsing floating point
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy numbers. Their syntax is locale dependent (i.e. "5.000" in en_US is
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy generally understood as 5, while on de_DE as 5000.).
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy- Try to use this:
1d32ba663e202c24a5a1f2e5aef83fffb447cb7fJohn Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy void foo() {
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy }
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy instead of this:
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy void foo()
f38cb554a534c6df738be3f4d23327e69888e634John Wren Kennedy {
}
But it's OK if you don't.
- Don't write "foo ()", write "foo()".
- Please use streq() and strneq() instead of strcmp(), strncmp() where applicable.
- Please do not allocate variables on the stack in the middle of code,
even if C99 allows it. Wrong:
{
a = 5;
int b;
b = a;
}
Right:
{
int b;
a = 5;
b = a;
}
- Unless you allocate an array, "double" is always the better choice
than "float". Processors speak "double" natively anyway, so this is
no speed benefit, and on calls like printf() "float"s get upgraded
to "double"s anyway, so there is no point.
- Don't invoke functions when you allocate variables on the stack. Wrong:
{
int a = foobar();
uint64_t x = 7;
}
Right:
{
int a;
uint64_t x = 7;
a = foobar();
}
- Use "goto" for cleaning up, and only use it for that. i.e. you may
only jump to the end of a function, and little else. Never jump
backwards!
- Think about the types you use. If a value cannot sensibly be
negative, don't use "int", but use "unsigned".
- Don't use types like "short". They *never* make sense. Use ints,
longs, long longs, all in unsigned+signed fashion, and the fixed
size types uint32_t and so on, as well as size_t, but nothing else.
- Public API calls (i.e. functions exported by our shared libraries)
must be marked "_public_" and need to be prefixed with "sd_". No
other functions should be prefixed like that.
- In public API calls, you *must* validate all your input arguments for
programming error with assert_return() and return a sensible return
code. In all other calls, it is recommended to check for programming
errors with a more brutal assert(). We are more forgiving to public
users then for ourselves! Note that assert() and assert_return()
really only should be used for detecting programming errors, not for
runtime errors. assert() and assert_return() by usage of _likely_()
inform the compiler that he shouldn't expect these checks to fail,
and they inform fellow programmers about the expected validity and
range of parameters.
- Never use strtol(), atoi() and similar calls. Use safe_atoli(),
safe_atou32() and suchlike instead. They are much nicer to use in
most cases and correctly check for parsing errors.
- For every function you add, think about whether it is a "logging"
function or a "non-logging" function. "Logging" functions do logging
on their own, "non-logging" function never log on their own and
expect their callers to log. All functions in "library" code,
i.e. in src/shared/ and suchlike must be "non-logging". Everytime a
"logging" function calls a "non-logging" function, it should log
about the resulting errors. If a "logging" function calls another
"logging" function, then it should not generate log messages, so
that log messages are not generated twice for the same errors.
- Avoid static variables, except for caches and very few other
cases. Think about thread-safety! While most of our code is never
used in threaded environments, at least the library code should make
sure it works correctly in them. Instead of doing a lot of locking
for that, we tend to prefer using TLS to do per-thread caching (which
only works for small, fixed-size cache objects), or we disable
caching for any thread that is not the main thread. Use
is_main_thread() to detect whether the calling thread is the main
thread.