]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
process-util: don't install atfork() handler more than once
authorLennart Poettering <lennart@poettering.net>
Mon, 26 Feb 2018 19:50:57 +0000 (20:50 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 28 Feb 2018 09:01:16 +0000 (10:01 +0100)
src/basic/process-util.c

index 66a7557fba3be71d9199fd768cba706bf2afec67..aa9846db5dc1373e63c14338fe6d342b364413f2 100644 (file)
@@ -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;