X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=CODING_STYLE;h=f13f9becbc0839d246ebffa44c34bcfee6963f72;hp=0b1f809e79717812c0fdd007e1ef5786a5f4e916;hb=ebbacbdb00c1452efb4a2f4077cf25136879e53d;hpb=dd4540da0e1f983540d862cc657df7161a3bdd06 diff --git a/CODING_STYLE b/CODING_STYLE index 0b1f809e7..f13f9becb 100644 --- a/CODING_STYLE +++ b/CODING_STYLE @@ -1,4 +1,9 @@ -- 8ch indent, no tabs +- 8ch indent, no tabs, except for files in man/ which are 2ch indent, + and still no tabs + +- We prefer /* comments */ over // comments, please. This is not C++, after + all. (Yes we know that C99 supports both kinds of comments, but still, + please!) - 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 @@ -116,7 +121,8 @@ no speed benefit, and on calls like printf() "float"s get promoted to "double"s anyway, so there is no point. -- Do not invoke functions when you allocate variables on the stack. Wrong: +- Do not mix function invocations with variable definitions in one + line. Wrong: { int a = foobar(); @@ -141,7 +147,9 @@ - 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. Do not use kernel types like u32 and so on, leave that to the + kernel. - Public API calls (i.e. functions exported by our shared libraries) must be marked "_public_" and need to be prefixed with "sd_". No @@ -194,4 +202,112 @@ - 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. + 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 POSIX version of basename() (which glibc defines it in + libgen.h), only the GNU version (which glibc defines in string.h). + The only reason to include libgen.h 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 POSIX 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. + +- When you define a destructor or unref() call for an object, please + accept a NULL object and simply treat this as NOP. This is similar + to how libc free() works, which accepts NULL pointers and becomes a + NOP for them. By following this scheme a lot of if checks can be + removed before invoking your destructor, which makes the code + substantially more readable and robust. + +- Related to this: when you define a destructor or unref() call for an + object, please make it return the same type it takes and always + return NULL from it. This allows writing code like this: + + p = foobar_unref(p); + + which will always work regardless if p is initialized or not, and + guarantees that p is NULL afterwards, all in just one line. + +- Use alloca(), but never forget that it is not OK to invoke alloca() + within a loop or within function call parameters. alloca() memory is + released at the end of a function, and not at the end of a {} + block. Thus, if you invoke it in a loop, you keep increasing the + stack pointer without ever releasing memory again. (VLAs have better + behaviour in this case, so consider using them as an alternative.) + Regarding not using alloca() within function parameters, see the + BUGS section of the alloca(3) man page. + +- Use memzero() or even better zero() instead of memset(..., 0, ...) + +- Instead of using memzero()/memset() to initialize structs allocated + on the stack, please try to use c99 structure initializers. It's + short, prettier and actually even faster at execution. Hence: + + struct foobar t = { + .foo = 7, + .bar = "bazz", + }; + + instead of: + + struct foobar t; + zero(t); + t.foo = 7; + t.bar = "bazz"; + +- When returning a return code from main(), please preferably use + EXIT_FAILURE and EXIT_SUCCESS as defined by libc. + +- The order in which header files are included doesn't matter too + much. systemd-internal headers must not rely on an include order, so + it is safe to include them in any order possible. + However, to not clutter global includes, and to make sure internal + definitions will not affect global headers, please always include the + headers of external components first (these are all headers enclosed + in <>), followed by our own exported headers (usually everything + that's prefixed by "sd-"), and then followed by internal headers. + Furthermore, in all three groups, order all includes alphabetically + so duplicate includes can easily be detected. + +- To implement an endless loop, use "for (;;)" rather than "while + (1)". The latter is a bit ugly anyway, since you probably really + meant "while (true)"... To avoid the discussion what the right + always-true expression for an infinite while() loop is our + recommendation is to simply write it without any such expression by + using "for (;;)".