X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=CODING_STYLE;h=feb1a9dd6715ef3731830e99c4b8bf6019d42773;hp=996897bcde976479faf2845d6ca7a5f6f9930250;hb=9ff3e22aa93fe461f8971f2468c65dc928fadc9e;hpb=d3a485135a98184cba28992752834a1bb4769003 diff --git a/CODING_STYLE b/CODING_STYLE index 996897bcd..feb1a9dd6 100644 --- a/CODING_STYLE +++ b/CODING_STYLE @@ -1,5 +1,9 @@ +- 8ch indent, no tabs, except for files in man/ which are 2ch indent, + and still no tabs -- 8ch indent, no tabs +- Don't break code lines too eagerly. We do *not* force line breaks at + 80ch, all of today's screens should be much larger than that. But + then again, don't overdo it, ~140ch should be enough really. - Variables and functions *must* be static, unless they have a prototype, and are supposed to be exported. @@ -10,27 +14,27 @@ - The destructors always unregister the object from the next bigger object, not the other way around -- To minimize strict aliasing violations we prefer unions over casting +- To minimize strict aliasing violations, we prefer unions over casting -- For robustness reasons destructors should be able to destruct +- For robustness reasons, destructors should be able to destruct half-initialized objects, too -- Error codes are returned as negative Exxx. i.e. return -EINVAL. There - are some exceptions: for constructors its is OK to return NULL on - OOM. For lookup functions NULL is fine too for "not found". +- Error codes are returned as negative Exxx. e.g. return -EINVAL. There + are some exceptions: for constructors, it is OK to return NULL on + OOM. For lookup functions, NULL is fine too for "not found". Be strict with this. When you write a function that can fail due to more than one cause, it *really* should have "int" as return value for the error code. -- Don't bother with error checking whether writing to stdout/stderr +- Do not bother with error checking whether writing to stdout/stderr worked. - Do not log errors from "library" code, only do so from "main - program" code. (With one exception: it's OK to log with DEBUG level + program" code. (With one exception: it is OK to log with DEBUG level from any code, with the exception of maybe inner loops). -- Always check OOM. There's no excuse. In program code you can use +- Always check OOM. There is no excuse. In program code, you can use "log_oom()" for then printing a short message, but not in "library" code. - Do not issue NSS requests (that includes user name and host name @@ -38,14 +42,14 @@ lookups involve synchronously talking to services that we would need to start up -- Don't synchronously talk to any other service from PID 1, due to +- Do not synchronously talk to any other service from PID 1, due to risk of deadlocks -- Avoid fixed sized string buffers, unless you really know the maximum +- Avoid fixed-size string buffers, unless you really know the maximum size and that maximum size is small. They are a source of errors, - since they possibly result in truncated strings. Often it is nicer - to use dynamic memory, alloca() or VLAs. If you do allocate fixed - size strings on the stack, then it's probably only OK if you either + since they possibly result in truncated strings. It is often nicer + to use dynamic memory, alloca() or VLAs. If you do allocate fixed-size + strings on the stack, then it is probably only OK if you either use a maximum size such as LINE_MAX, or count in detail the maximum size a string can have. (DECIMAL_STR_MAX and DECIMAL_STR_WIDTH macros are your friends for this!) @@ -54,7 +58,7 @@ doing something wrong! - Stay uniform. For example, always use "usec_t" for time - values. Don't usec mix msec, and usec and whatnot. + values. Do not mix usec and msec, and usec and whatnot. - Make use of _cleanup_free_ and friends. It makes your code much nicer to read! @@ -74,9 +78,20 @@ { } - But it's OK if you don't. + But it is OK if you do not. -- Don't write "foo ()", write "foo()". +- Single-line "if" blocks should not be enclosed in {}. Use this: + + if (foobar) + waldo(); + + instead of this: + + if (foobar) { + waldo(); + } + +- Do not write "foo ()", write "foo()". - Please use streq() and strneq() instead of strcmp(), strncmp() where applicable. @@ -99,10 +114,10 @@ - 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 + no speed benefit, and on calls like printf() "float"s get promoted to "double"s anyway, so there is no point. -- Don't invoke functions when you allocate variables on the stack. Wrong: +- Do not invoke functions when you allocate variables on the stack. Wrong: { int a = foobar(); @@ -123,24 +138,24 @@ backwards! - Think about the types you use. If a value cannot sensibly be - negative don't use "int", but use "unsigned". + negative, do not use "int", but use "unsigned". -- Don't use types like "short". They *never* make sense. Use ints, +- Do not 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. + 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 +- 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 + 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, + inform the compiler that he should not expect these checks to fail, and they inform fellow programmers about the expected validity and range of parameters. @@ -152,18 +167,75 @@ 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 + i.e. in src/shared/ and suchlike must be "non-logging". Every time 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 + 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 + 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. + +- Command line option parsing: + - Do not print full help() on error, be specific about the error. + - Do not print messages to stdout on error. + - Do not POSIX_ME_HARDER unless necessary, i.e. avoid "+" in option string. + +- Do not write functions that clobber call-by-reference variables on + failure. Use temporary variables for these cases and change the + passed in variables only on success. + +- When you allocate a file descriptor, it should be made O_CLOEXEC + right from the beginning, as none of our files should leak to forked + binaries by default. Hence, whenever you open a file, O_CLOEXEC must + be specified, right from the beginning. This also applies to + sockets. Effectively this means that all invocations to: + + a) open() must get O_CLOEXEC passed + b) socket() and socketpair() must get SOCK_CLOEXEC passed + c) recvmsg() must get MSG_CMSG_CLOEXEC set + d) F_DUPFD_CLOEXEC should be used instead of F_DUPFD, and so on + +- We never use the XDG version of basename(). glibc defines it in + libgen.h. The only reason to include that file is because dirname() + is needed. Everytime you need that please immediately undefine + basename(), and add a comment about it, so that no code ever ends up + using the XDG version! + +- Use the bool type for booleans, not integers. One exception: in public + headers (i.e those in src/systemd/sd-*.h) use integers after all, as "bool" + is C99 and in our public APIs we try to stick to C89 (with a few extension). + +- When you invoke certain calls like unlink(), or mkdir_p() and you + know it is safe to ignore the error it might return (because a later + call would detect the failure anyway, or because the error is in an + error path and you thus couldn't do anything about it anyway), then + make this clear by casting the invocation explicitly to (void). Code + checks like Coverity understand that, and will not complain about + ignored error codes. Hence, please use this: + + (void) unlink("/foo/bar/baz"); + + instead of just this: + + unlink("/foo/bar/baz"); + +- Don't invoke exit(), ever. It is not replacement for proper error + handling. Please escalate errors up your call chain, and use normal + "return" to exit from the main function of a process. If you + fork()ed off a child process, please use _exit() instead of exit(), + so that the exit handlers are not run. + +- Please never use dup(). Use fcntl(fd, F_DUPFD_CLOEXEC, 3) + instead. For two reason: first, you want O_CLOEXEC set on the new fd + (see above). Second, dup() will happily duplicate your fd as 0, 1, + 2, i.e. stdin, stdout, stderr, should those fds be closed. Given the + special semantics of those fds, it's probably a good idea to avoid + them. F_DUPFD_CLOEXEC with "3" as parameter avoids them.