From d9cb34abb40c547325dbf24e8986698dffc9ffa8 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Fri, 11 Sep 2015 21:33:17 +0200 Subject: [PATCH] Add some notes about coding conventions do the docs. This deserves to be greatly expanded and improved, but it's a start. Discussion: 20150827145219.GI2435@awork2.anarazel.de --- doc/src/sgml/sources.sgml | 105 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/doc/src/sgml/sources.sgml b/doc/src/sgml/sources.sgml index d6461ec3f2..fcb3e402f8 100644 --- a/doc/src/sgml/sources.sgml +++ b/doc/src/sgml/sources.sgml @@ -851,4 +851,109 @@ BETTER: unrecognized node type: 42 + + Miscellaneous Coding Conventions + + + C Standard + + Code in PostgreSQL should only rely on language + features available in the C89 standard. That means a conforming + C89 compiler has to be able to compile postgres, at least aside + from a few platform dependant pieces. Features from later + revision of the C standard or compiler specific features can be + used, if a fallback is provided. + + + For example static inline and + _StaticAssert() are currently used, even + though they are from newer revisions of the C standard. If not + available we respectively fall back to defining the functions + without inline, and to using a C89 compatible replacement that + performs the same checks, but emits rather cryptic messages. + + + + + Function-Like Macros and Inline Functions + + Both, macros with arguments and static inline + functions, may be used. The latter are preferable if there are + multiple-evaluation hazards when written as a macro, as e.g. the + case with + +#define Max(x, y) ((x) > (y) ? (x) : (y)) + + or when the macro would be very long. In other cases it's only + possible to use macros, or at least easier. For example because + expressions of various types need to be passed to the macro. + + + When the definition an inline function references symbols + (i.e. variables, functions) that are only available as part of the + backend, the function may not be visible when included from frontend + code. + +#ifndef FRONTEND +static inline MemoryContext +MemoryContextSwitchTo(MemoryContext context) +{ + MemoryContext old = CurrentMemoryContext; + + CurrentMemoryContext = context; + return old; +} +#endif /* FRONTEND */ + + In this example CurrentMemoryContext, which is only + available in the backend, is referenced and the function thus + hidden with a #ifndef FRONTEND. This rule + exists because some compilers emit references to symbols + contained in inline functions even if the function is not used. + + + + + Writing Signal Handlers + + To be suitable to run inside a signal handler code has to be + written very carefully. The fundamental problem is that, unless + blocked, a signal handler can interrupt code at any time. If code + inside the signal handler uses the same state as code outside + chaos may ensue. As an example consider what happens if a signal + handler tries to acquire a lock that's already held in the + interrupted code. + + + Barring special arrangements code in signal handlers may only + call async-signal safe functions (as defined in posix) and access + variables of type volatile sig_atomic_t. A few + functions in postgres are also deemed signal safe, importantly + SetLatch(). + + + In most cases signal handlers should do nothing more than note + that a signal has arrived, and wake up code running outside of + the handler using a latch. An example of such a handler is the + following: + +static void +handle_sighup(SIGNAL_ARGS) +{ + int save_errno = errno; + + got_SIGHUP = true; + SetLatch(MyLatch); + + errno = save_errno; +} + + errno is safed and restored because + SetLatch() might change it. If that were not done + interrupted code that's currently inspecting errno might see the wrong + value. + + + + -- 2.40.0