summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2018-02-26 20:50:57 +0100
committerSven Eden <yamakuzure@gmx.net>2018-05-30 07:59:08 +0200
commitd177b5ffe6a5a5273d8e075dca1716cc926839c4 (patch)
treea4f95ca5a362aff548c038c6f908c721560c78b4 /src
parentecc6cb9a01b132b88cdf20272573c142eeb84e8b (diff)
process-util: don't install atfork() handler more than once
Diffstat (limited to 'src')
-rw-r--r--src/basic/process-util.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index 03d42c07d..1ebfb0c72 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -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;