logind: handle session leader termination during deserialization more gracefully (#39607)

Closes https://github.com/systemd/systemd/issues/39556
This commit is contained in:
Yu Watanabe
2025-11-07 16:35:32 +09:00
committed by GitHub
2 changed files with 14 additions and 11 deletions

View File

@@ -423,6 +423,8 @@ static int session_load_leader(Session *s, uint64_t pidfdid) {
return 0;
r = pidref_set_pid(&pidref, s->deserialized_pid);
if (r == -ESRCH)
return log_warning_errno(r, "Leader of session '%s' is gone while deserializing.", s->id);
if (r < 0)
return log_error_errno(r, "Failed to deserialize leader PID for session '%s': %m", s->id);
if (pidref.fd < 0)
@@ -437,9 +439,9 @@ static int session_load_leader(Session *s, uint64_t pidfdid) {
pidref.pid);
if (pidref.fd_id != pidfdid)
return log_error_errno(SYNTHETIC_ERRNO(ESRCH),
"Deserialized pidfd id for process " PID_FMT " (%" PRIu64 ") doesn't match with the current one (%" PRIu64 "), refusing.",
pidref.pid, pidfdid, pidref.fd_id);
return log_warning_errno(SYNTHETIC_ERRNO(ESRCH),
"Deserialized pidfd id for process " PID_FMT " (%" PRIu64 ") doesn't match the current one (%" PRIu64 "). PID recycled while deserializing?",
pidref.pid, pidfdid, pidref.fd_id);
}
r = session_set_leader_consume(s, TAKE_PIDREF(pidref));

View File

@@ -441,13 +441,13 @@ static int deliver_session_device_fd(Session *s, const char *fdname, int fd, dev
return 0;
}
static int deliver_session_leader_fd_consume(Session *s, const char *fdname, int fd) {
static int deliver_session_leader_fd_consume(Session *s, const char *fdname, int fd_consume) {
_cleanup_close_ int fd = ASSERT_FD(fd_consume);
_cleanup_(pidref_done) PidRef leader_fdstore = PIDREF_NULL;
int r;
assert(s);
assert(fdname);
assert(fd >= 0);
/* Already deserialized via pidfd id? */
if (pidref_is_set(&s->leader)) {
@@ -473,12 +473,13 @@ static int deliver_session_leader_fd_consume(Session *s, const char *fdname, int
r = pidref_set_pidfd_take(&leader_fdstore, fd);
if (r < 0) {
if (r == -ESRCH)
log_debug_errno(r, "Leader of session '%s' is gone while deserializing.", s->id);
else
log_warning_errno(r, "Failed to create reference to leader of session '%s': %m", s->id);
log_warning_errno(r,
r == -ESRCH ? "Leader of session '%s' is gone while deserializing."
: "Failed to create reference to leader of session '%s': %m",
s->id);
goto fail_close;
}
TAKE_FD(fd);
if (leader_fdstore.pid != s->deserialized_pid)
log_warning("Leader from pidfd (" PID_FMT ") doesn't match with LEADER=" PID_FMT " for session '%s', proceeding anyway.",
@@ -491,7 +492,7 @@ static int deliver_session_leader_fd_consume(Session *s, const char *fdname, int
return 0;
fail_close:
close_and_notify_warn(fd, fdname);
close_and_notify_warn(TAKE_FD(fd), fdname);
return r;
}
@@ -565,7 +566,7 @@ static int manager_enumerate_sessions(Manager *m) {
session_add_to_gc_queue(s);
k = session_load(s);
if (k < 0)
if (k < 0 && k != -ESRCH)
RET_GATHER(r, log_warning_errno(k, "Failed to deserialize session '%s', ignoring: %m", s->id));
}