From: Lennart Poettering Date: Fri, 1 Dec 2023 16:14:33 +0000 (+0100) Subject: pidref: add pidref_set_parent() for race-freely getting pidref on ppid X-Git-Tag: v256-rc1~1497 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a1796e9bd889ec8e5f3e8205b255bb11b9229cb5;p=thirdparty%2Fsystemd.git pidref: add pidref_set_parent() for race-freely getting pidref on ppid --- diff --git a/src/basic/pidref.c b/src/basic/pidref.c index 69b5cad5759..d3821c1f544 100644 --- a/src/basic/pidref.c +++ b/src/basic/pidref.c @@ -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); diff --git a/src/basic/pidref.h b/src/basic/pidref.h index dada069357d..a01d4cc85ba 100644 --- a/src/basic/pidref.h +++ b/src/basic/pidref.h @@ -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); }