From: Lennart Poettering Date: Mon, 26 Feb 2018 19:50:57 +0000 (+0100) Subject: process-util: don't install atfork() handler more than once X-Git-Tag: v238~37^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5d71bac3b926493cbc31741c52e7d89c3296dfb3;p=thirdparty%2Fsystemd.git process-util: don't install atfork() handler more than once --- diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 66a7557fba3..aa9846db5dc 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -1166,6 +1166,7 @@ extern int __register_atfork(void (*prepare) (void), void (*parent) (void), void extern void* __dso_handle __attribute__ ((__weak__)); pid_t getpid_cached(void) { + static bool installed = false; pid_t current_value; /* getpid_cached() is much like getpid(), but caches the value in local memory, to avoid having to invoke a @@ -1186,10 +1187,18 @@ pid_t getpid_cached(void) { new_pid = raw_getpid(); - if (__register_atfork(NULL, NULL, reset_cached_pid, __dso_handle) != 0) { - /* OOM? Let's try again later */ - cached_pid = CACHED_PID_UNSET; - return new_pid; + if (!installed) { + /* __register_atfork() either returns 0 or -ENOMEM, in its glibc implementation. Since it's + * only half-documented (glibc doesn't document it but LSB does — though only superficially) + * we'll check for errors only in the most generic fashion possible. */ + + if (__register_atfork(NULL, NULL, reset_cached_pid, __dso_handle) != 0) { + /* OOM? Let's try again later */ + cached_pid = CACHED_PID_UNSET; + return new_pid; + } + + installed = true; } cached_pid = new_pid;