]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
process-util: Use pidref_wait_for_terminate_and_check in pidref_safe_fork()
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 18 Dec 2025 09:28:30 +0000 (10:28 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Sat, 20 Dec 2025 14:44:20 +0000 (15:44 +0100)
Note that we still have to block SIGCHLD so that
we can be certain the process is not reaped before
we get the pidfd to it. safe_fork() and friends are
used in libsystemd where we don't control how the
SIGCHLD signal is configured. Specifically, kernel
autoreaping could be enabled which is why we have
to block SIGCHLD until we get the pidfd so that the
kernel cannot autoreap the process before we get
the pidfd.

src/basic/process-util.c

index f25f4b81e51d2e977444886b6b13d59d1ad49044..e319214f4aab267016d411dbd01c7ab0ce9fd5bd 100644 (file)
@@ -1566,9 +1566,13 @@ int pidref_safe_fork_full(
                                 pidref_transport_fds[1] = safe_close(pidref_transport_fds[1]);
 
                                 if (pidref_transport_fds[0] >= 0) {
-                                        /* Wait for the intermediary child to exit so the caller can be certain the actual child
-                                         * process has been reparented by the time this function returns. */
-                                        r = wait_for_terminate_and_check(name, pid, FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
+                                        /* Wait for the intermediary child to exit so the caller can be
+                                         * certain the actual child process has been reparented by the time
+                                         * this function returns. */
+                                        r = pidref_wait_for_terminate_and_check(
+                                                        name,
+                                                        &PIDREF_MAKE_FROM_PID(pid),
+                                                        FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
                                         if (r < 0)
                                                 return log_full_errno(prio, r, "Failed to wait for intermediary process: %m");
                                         if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */
@@ -1644,7 +1648,10 @@ int pidref_safe_fork_full(
                                 (void) sigprocmask(SIG_SETMASK, &ss, NULL);
                         }
 
-                        r = wait_for_terminate_and_check(name, pid, (flags & FORK_LOG ? WAIT_LOG : 0));
+                        r = pidref_wait_for_terminate_and_check(
+                                        name,
+                                        &PIDREF_MAKE_FROM_PID(pid),
+                                        FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
                         if (r < 0)
                                 return r;
                         if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */