chiark / gitweb /
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)
committerSven Eden <yamakuzure@gmx.net>
Wed, 30 May 2018 05:59:08 +0000 (07:59 +0200)
src/basic/process-util.c

index 03d42c07d29f8ad418226d83f993b3efe4963119..1ebfb0c7297c7186a01b39bdb4847423bd2001e0 100644 (file)
@@ -1180,6 +1180,7 @@ extern void* __dso_handle __attribute__ ((__weak__));
 #endif // ifdef __GLIBC__
 
 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
@@ -1200,10 +1201,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;