if NO_PIDFD_SUPPORT.load(Relaxed) { return None;
}
// Safety: The following function calls invovkes syscall pidfd_open, // which takes two parameter: pidfd_open(fd: c_int, flag: c_int) let fd = unsafe { syscall(SYS_pidfd_open, pid, PIDFD_NONBLOCK) }; if fd == -1 { let errno = io::Error::last_os_error().raw_os_error().unwrap();
if errno == ENOSYS {
NO_PIDFD_SUPPORT.store(true, Relaxed)
}
None
} else { // Safety: pidfd_open returns -1 on error or a valid fd with ownership.
Some(Pidfd {
fd: unsafe { File::from_raw_fd(fd as i32) },
})
}
}
}
#[allow(deprecated)] fn is_rt_shutdown_err(err: &io::Error) -> bool { iflet Some(inner) = err.get_ref() { // Using `Error::description()` is more efficient than `format!("{inner}")`, // so we use it here even if it is deprecated.
err.kind() == io::ErrorKind::Other
&& inner.source().is_none()
&& inner.description() == RUNTIME_SHUTTING_DOWN_ERROR
} else { false
}
}
impl<W> Future for PidfdReaperInner<W> where
W: Wait + Unpin,
{ type Output = io::Result<ExitStatus>;
fn poll(self: Pin<&mutSelf>, cx: &mut Context<'_>) -> Poll<Self::Output> { let this = Pin::into_inner(self);
match ready!(this.pidfd.poll_read_ready(cx)) {
Err(err) if is_rt_shutdown_err(&err) => {
this.pidfd.reregister(Interest::READABLE)?;
ready!(this.pidfd.poll_read_ready(cx))?
}
res => res?,
}
Poll::Ready(Ok(this
.inner
.try_wait()?
.expect("pidfd is ready to read, the process should have exited")))
}
}
#[derive(Debug)] pub(crate) struct PidfdReaper<W, Q> where
W: Wait + Unpin,
Q: OrphanQueue<W> + Unpin,
{
inner: Option<PidfdReaperInner<W>>,
orphan_queue: Q,
}
impl<W, Q> Deref for PidfdReaper<W, Q> where
W: Wait + Unpin,
Q: OrphanQueue<W> + Unpin,
{ type Target = W;
impl<W, Q> Drop for PidfdReaper<W, Q> where
W: Wait + Unpin,
Q: OrphanQueue<W> + Unpin,
{ fn drop(&mutself) { letmut orphan = self.inner.take().expect("inner has gone away").inner; iflet Ok(Some(_)) = orphan.try_wait() { return;
}
self.orphan_queue.push_orphan(orphan);
}
}
#[cfg(all(test, not(loom), not(miri)))] mod test { usesuper::*; usecrate::{
process::unix::orphan::test::MockQueue,
runtime::{Builder as RuntimeBuilder, Runtime},
}; use std::process::{Command, Output};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.