pidref: Add pidref_wait_for_terminate_full()

We can use this to replace wait_for_terminate_with_timeout(). Because
we poll a pidfd, we don't need to block SIGCHLD anymore in umount.c.
This commit is contained in:
Daan De Meyer
2025-12-20 15:49:26 +01:00
parent 9bd833ee6e
commit e74b571004
9 changed files with 122 additions and 123 deletions
+36 -18
View File
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <poll.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -8,12 +9,14 @@
#include "fd-util.h"
#include "format-util.h"
#include "hash-funcs.h"
#include "io-util.h"
#include "log.h"
#include "parse-util.h"
#include "pidfd-util.h"
#include "pidref.h"
#include "process-util.h"
#include "siphash24.h"
#include "time-util.h"
int pidref_acquire_pidfd_id(PidRef *pidref) {
int r;
@@ -449,7 +452,8 @@ bool pidref_is_self(PidRef *pidref) {
return pidref->fd_id == self_id;
}
int pidref_wait(PidRef *pidref, siginfo_t *ret, int options) {
int pidref_wait_for_terminate_full(PidRef *pidref, usec_t timeout, siginfo_t *ret) {
siginfo_t si = {};
int r;
if (!pidref_is_set(pidref))
@@ -461,13 +465,37 @@ int pidref_wait(PidRef *pidref, siginfo_t *ret, int options) {
if (pidref->pid == 1 || pidref_is_self(pidref))
return -ECHILD;
siginfo_t si = {};
if (pidref->fd >= 0)
r = RET_NERRNO(waitid(P_PIDFD, pidref->fd, &si, options));
else
r = RET_NERRNO(waitid(P_PID, pidref->pid, &si, options));
if (r < 0)
return r;
if (timeout != USEC_INFINITY && pidref->fd < 0)
return -ENOMEDIUM;
usec_t ts = timeout == USEC_INFINITY ? USEC_INFINITY : now(CLOCK_MONOTONIC) + timeout;
for (;;) {
if (timeout != USEC_INFINITY) {
usec_t left = usec_sub_unsigned(ts, now(CLOCK_MONOTONIC));
if (left == 0)
return -ETIMEDOUT;
r = fd_wait_for_event(pidref->fd, POLLIN, left);
if (r == 0)
return -ETIMEDOUT;
if (r == -EINTR)
continue;
if (r < 0)
return r;
}
if (pidref->fd >= 0)
r = RET_NERRNO(waitid(P_PIDFD, pidref->fd, &si, WEXITED));
else
r = RET_NERRNO(waitid(P_PID, pidref->pid, &si, WEXITED));
if (r == -EINTR)
continue;
if (r < 0)
return r;
break;
}
if (ret)
*ret = si;
@@ -475,16 +503,6 @@ int pidref_wait(PidRef *pidref, siginfo_t *ret, int options) {
return 0;
}
int pidref_wait_for_terminate(PidRef *pidref, siginfo_t *ret) {
int r;
for (;;) {
r = pidref_wait(pidref, ret, WEXITED);
if (r != -EINTR)
return r;
}
}
bool pidref_is_automatic(const PidRef *pidref) {
return pidref && pid_is_automatic(pidref->pid);
}