From d9cb34abb40c547325dbf24e8986698dffc9ffa8 Mon Sep 17 00:00:00 2001 From: Andres Freund <andres@anarazel.de> 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 d6461ec3f2a..fcb3e402f85 100644 --- a/doc/src/sgml/sources.sgml +++ b/doc/src/sgml/sources.sgml @@ -851,4 +851,109 @@ BETTER: unrecognized node type: 42 </sect1> + <sect1 id="source-conventions"> + <title>Miscellaneous Coding Conventions</title> + + <simplesect> + <title>C Standard</title> + <para> + Code in <productname>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. + </para> + <para> + For example <literal>static inline</> and + <literal>_StaticAssert()</literal> 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. + </para> + </simplesect> + + <simplesect> + <title>Function-Like Macros and Inline Functions</title> + <para> + Both, macros with arguments and <literal>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 +<programlisting> +#define Max(x, y) ((x) > (y) ? (x) : (y)) +</programlisting> + 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. + </para> + <para> + 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. +<programlisting> +#ifndef FRONTEND +static inline MemoryContext +MemoryContextSwitchTo(MemoryContext context) +{ + MemoryContext old = CurrentMemoryContext; + + CurrentMemoryContext = context; + return old; +} +#endif /* FRONTEND */ +</programlisting> + In this example <literal>CurrentMemoryContext</>, which is only + available in the backend, is referenced and the function thus + hidden with a <literal>#ifndef FRONTEND</literal>. This rule + exists because some compilers emit references to symbols + contained in inline functions even if the function is not used. + </para> + </simplesect> + + <simplesect> + <title>Writing Signal Handlers</title> + <para> + 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. + </para> + <para> + Barring special arrangements code in signal handlers may only + call async-signal safe functions (as defined in posix) and access + variables of type <literal>volatile sig_atomic_t</literal>. A few + functions in postgres are also deemed signal safe, importantly + <literal>SetLatch()</literal>. + </para> + <para> + 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: +<programlisting> +static void +handle_sighup(SIGNAL_ARGS) +{ + int save_errno = errno; + + got_SIGHUP = true; + SetLatch(MyLatch); + + errno = save_errno; +} +</programlisting> + <literal>errno</> is safed and restored because + <literal>SetLatch()</> might change it. If that were not done + interrupted code that's currently inspecting errno might see the wrong + value. + </para> + </simplesect> + + </sect1> </chapter> -- GitLab