diff --git a/src/libsystemd/sd-event/event-util.c b/src/libsystemd/sd-event/event-util.c index 47cf76f9c2..d4e986fc49 100644 --- a/src/libsystemd/sd-event/event-util.c +++ b/src/libsystemd/sd-event/event-util.c @@ -165,19 +165,49 @@ int event_add_time_change(sd_event *e, sd_event_source **ret, sd_event_io_handle int event_add_child_pidref( sd_event *e, - sd_event_source **s, + sd_event_source **ret, const PidRef *pid, int options, sd_event_child_handler_t callback, void *userdata) { + int r; + + assert(e); + if (!pidref_is_set(pid)) return -ESRCH; - if (pid->fd >= 0) - return sd_event_add_child_pidfd(e, s, pid->fd, options, callback, userdata); + if (pidref_is_remote(pid)) + return -EREMOTE; - return sd_event_add_child(e, s, pid->pid, options, callback, userdata); + if (pid->fd < 0) + return sd_event_add_child(e, ret, pid->pid, options, callback, userdata); + + _cleanup_close_ int copy_fd = fcntl(pid->fd, F_DUPFD_CLOEXEC, 3); + if (copy_fd < 0) + return -errno; + + _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL; + r = sd_event_add_child_pidfd(e, &s, copy_fd, options, callback, userdata); + if (r < 0) + return r; + + r = sd_event_source_set_child_pidfd_own(s, true); + if (r < 0) + return r; + + TAKE_FD(copy_fd); + + if (ret) + *ret = TAKE_PTR(s); + else { + r = sd_event_source_set_floating(s, true); + if (r < 0) + return r; + } + + return 0; } int event_source_get_child_pidref(sd_event_source *s, PidRef *ret) { diff --git a/src/vmspawn/vmspawn.c b/src/vmspawn/vmspawn.c index d616f2c7ab..294775d03e 100644 --- a/src/vmspawn/vmspawn.c +++ b/src/vmspawn/vmspawn.c @@ -2350,7 +2350,9 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) { log_debug_errno(r, "Failed allocate memory pressure event source, ignoring: %m"); /* Exit when the child exits */ - (void) event_add_child_pidref(event, NULL, &child_pidref, WEXITED, on_child_exit, NULL); + r = event_add_child_pidref(event, /* ret_event_source= */ NULL, &child_pidref, WEXITED, on_child_exit, /* userdata= */ NULL); + if (r < 0) + return log_error_errno(r, "Failed to watch qemu process: &m"); _cleanup_(osc_context_closep) sd_id128_t osc_context_id = SD_ID128_NULL; _cleanup_(pty_forward_freep) PTYForward *forward = NULL;