pidref: add pidref_set_parent() for race-freely getting pidref on ppid

This commit is contained in:
Lennart Poettering
2023-12-01 17:14:33 +01:00
parent f9ba9d3eb7
commit a1796e9bd8
2 changed files with 33 additions and 1 deletions

View File

@@ -106,6 +106,38 @@ int pidref_set_pidfd_consume(PidRef *pidref, int fd) {
return r;
}
int pidref_set_parent(PidRef *ret) {
_cleanup_(pidref_done) PidRef parent = PIDREF_NULL;
pid_t ppid;
int r;
assert(ret);
/* Acquires a pidref to our parent process. Deals with the fact that parent processes might exit, and
* we get reparented to other processes, with our old parent's PID already being recycled. */
ppid = getppid();
for (;;) {
r = pidref_set_pid(&parent, ppid);
if (r < 0)
return r;
if (parent.fd < 0) /* If pidfds are not available, then we are done */
break;
pid_t now_ppid = getppid();
if (now_ppid == ppid) /* If our ppid is still the same, then we are done */
break;
/* Otherwise let's try again with the new ppid */
ppid = now_ppid;
pidref_done(&parent);
}
*ret = TAKE_PIDREF(parent);
return 0;
}
void pidref_done(PidRef *pidref) {
assert(pidref);

View File

@@ -38,7 +38,7 @@ int pidref_set_pidstr(PidRef *pidref, const char *pid);
int pidref_set_pidfd(PidRef *pidref, int fd);
int pidref_set_pidfd_take(PidRef *pidref, int fd); /* takes ownership of the passed pidfd on success*/
int pidref_set_pidfd_consume(PidRef *pidref, int fd); /* takes ownership of the passed pidfd in both success and failure */
int pidref_set_parent(PidRef *ret);
static inline int pidref_set_self(PidRef *pidref) {
return pidref_set_pid(pidref, 0);
}