sd-event: make pidfd copy in event_add_child_pidref()
So far we'd directly use the pidfd passed into event_add_child_pidref(), hoping it would not be closed by the caller before we are done. This was violated by vmspawn however. Let's make this safe, and simply duplicate the fd, and make us independent of the caller.
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user