-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Description
Is your feature request related to a problem? Please describe.
tokio::process::Child::wait currently uses signal to decide whether or not the child might have exited.
Since signal can be dropped at arbitrary time, any SIGCHLD signal received would cause all tokio::process::Child::wait() future to be awakened and execute std::process::Child::try_wait to decide whether it's ready.
Describe the solution you'd like
On Linux, a better solution would be to use pidfd.
Since libstd support for pidfd is still unstable rust-lang/rust#82971, tokio can choose to either:
- port open pidfd in child process and send to the parent via SOCK_SEQPACKET+CMSG rust-lang/rust#113939 to tokio which guarantees 100% race free, the downsides is
vforkcannot be used and a lot of code will be added - use
pidfd_openin parent to open the pid, this isn't 100% race free but it might be a good start, it will be simple to implement andvforkcan continue to be used
And then the pidfd returned can be epolled and it will awake only one future when the process has exited, then waitid can be used to wait on the child in a race free manner.
(Or tokio can just continue to call std::process::Child::try_wait since holding a pidfd prevents the pid from being recycled.)
For tokio::process::Child::{kill, start_kill}, if we have a pidfd, then pidfd_send_signal is the most robust way of sending the signal to the right process.
According to pidfd_open:
Even if the child has already terminated by the time of the
pidfd_open()call, its PID will not have been recycled and the returned file descriptor will refer to the resulting zombie process.
So as long as the pidfd is held, existing implementation of tokio::process::Child::{kill, start_kill} should be race-free.
tokio can also have a new method:
use std::os::fd::BorrowedFd;
impl Child {
#[cfg(linux)]
fn pidfd(&self) -> Option<BorrowedFd<'_>>;
}Describe alternatives you've considered
Additional context