return pidref->fd_id == self_id;
}
-int pidref_wait_for_terminate_full(PidRef *pidref, usec_t timeout, siginfo_t *ret) {
- siginfo_t si = {};
+int pidref_wait_for_terminate_full(PidRef *pidref, usec_t timeout, siginfo_t *ret_si) {
int r;
+ assert(timeout > 0);
+
if (!pidref_is_set(pidref))
return -ESRCH;
if (timeout != USEC_INFINITY && pidref->fd < 0)
return -ENOMEDIUM;
- usec_t ts = timeout == USEC_INFINITY ? USEC_INFINITY : now(CLOCK_MONOTONIC) + timeout;
+ usec_t ts = timeout == USEC_INFINITY ? USEC_INFINITY : usec_add(now(CLOCK_MONOTONIC), timeout);
for (;;) {
- if (timeout != USEC_INFINITY) {
+ if (ts != USEC_INFINITY) {
usec_t left = usec_sub_unsigned(ts, now(CLOCK_MONOTONIC));
if (left == 0)
return -ETIMEDOUT;
return r;
}
+ siginfo_t si = {};
+
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)
+ if (r >= 0) {
+ if (ret_si)
+ *ret_si = si;
+ return 0;
+ }
+ if (r != -EINTR)
return r;
-
- break;
}
-
- if (ret)
- *ret = si;
-
- return 0;
}
bool pidref_is_automatic(const PidRef *pidref) {
int pidref_kill_and_sigcont(const PidRef *pidref, int sig);
int pidref_sigqueue(const PidRef *pidref, int sig, int value);
-int pidref_wait_for_terminate_full(PidRef *pidref, usec_t timeout, siginfo_t *ret);
-static inline int pidref_wait_for_terminate(PidRef *pidref, siginfo_t *ret) {
- return pidref_wait_for_terminate_full(pidref, USEC_INFINITY, ret);
+int pidref_wait_for_terminate_full(PidRef *pidref, usec_t timeout, siginfo_t *ret_si);
+static inline int pidref_wait_for_terminate(PidRef *pidref, siginfo_t *ret_si) {
+ return pidref_wait_for_terminate_full(pidref, USEC_INFINITY, ret_si);
}
static inline void pidref_done_sigterm_wait(PidRef *pidref) {
* SYNC_PROGRESS_ATTEMPTS lapse without progress being made,
* we assume that the sync is stalled */
for (unsigned checks = 0; checks < SYNC_PROGRESS_ATTEMPTS; checks++) {
- r = pidref_wait_for_terminate_full(&pidref, SYNC_TIMEOUT_USEC, /* ret= */ NULL);
+ r = pidref_wait_for_terminate_full(&pidref, SYNC_TIMEOUT_USEC, /* ret_si= */ NULL);
if (r == 0)
/* Sync finished without error (sync() call itself does not return an error code) */
return 0;
TEST(asynchronous_sync) {
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
ASSERT_OK(asynchronous_sync(&pidref));
- ASSERT_OK(pidref_wait_for_terminate(&pidref, /* ret= */ NULL));
+ ASSERT_OK(pidref_wait_for_terminate(&pidref, NULL));
}
static void wait_fd_closed(int fd) {
ASSERT_OK_ZERO(process_is_owned_by_uid(&pid, getuid()));
ASSERT_OK(pidref_kill(&pid, SIGKILL));
- ASSERT_OK(pidref_wait_for_terminate(&pid, /* ret= */ NULL));
+ ASSERT_OK(pidref_wait_for_terminate(&pid, NULL));
/* Test a child that runs in a userns as uid 1, but the userns is owned by us */
ASSERT_OK_ERRNO(pipe2(p, O_CLOEXEC));
ASSERT_OK_POSITIVE(process_is_owned_by_uid(&pid, getuid()));
ASSERT_OK(pidref_kill(&pid, SIGKILL));
- ASSERT_OK(pidref_wait_for_terminate(&pid, /* ret= */ NULL));
+ ASSERT_OK(pidref_wait_for_terminate(&pid, NULL));
}
TEST(namespace_get_leader) {
ASSERT_FALSE(pidref_is_automatic(&p));
ASSERT_ERROR(pidref_kill(&p, SIGTERM), EREMOTE);
ASSERT_ERROR(pidref_kill_and_sigcont(&p, SIGTERM), EREMOTE);
- ASSERT_ERROR(pidref_wait_for_terminate(&p, /* ret= */ NULL), EREMOTE);
+ ASSERT_ERROR(pidref_wait_for_terminate(&p, NULL), EREMOTE);
ASSERT_ERROR(pidref_verify(&p), EREMOTE);
}