Refactor `PidFile` to use `Weak<Process>`

This commit is contained in:
li041 2026-01-13 08:15:52 +00:00 committed by Tate, Hongliang Tian
parent 2219e83f8e
commit f58fb66cba
3 changed files with 26 additions and 15 deletions

View File

@ -22,7 +22,7 @@ use crate::{
};
pub struct PidFile {
process: Arc<Process>,
process: Weak<Process>,
is_nonblocking: AtomicBool,
/// The pseudo path associated with this pid file.
pseudo_path: Path,
@ -30,8 +30,9 @@ pub struct PidFile {
impl Debug for PidFile {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let pid = self.process.upgrade().map_or(u32::MAX, |p| p.pid());
f.debug_struct("PidFile")
.field("process", &self.process.pid())
.field("process", &pid)
.field(
"is_nonblocking",
&self.is_nonblocking.load(Ordering::Relaxed),
@ -45,7 +46,7 @@ impl PidFile {
let pseudo_path = AnonInodeFs::new_path(|_| "anon_inode:[pidfd]".to_string());
Self {
process,
process: Arc::downgrade(&process),
is_nonblocking: AtomicBool::new(is_nonblocking),
pseudo_path,
}
@ -56,7 +57,11 @@ impl PidFile {
// and epoll(7). When the process that it refers to terminates, these
// interfaces indicate the file descriptor as readable."
// Reference: <https://man7.org/linux/man-pages/man2/pidfd_open.2.html>.
if self.process.status().is_zombie() {
let Some(process) = self.process.upgrade() else {
// The process has been reaped.
return IoEvents::IN;
};
if process.status().is_zombie() {
IoEvents::IN
} else {
IoEvents::empty()
@ -67,8 +72,8 @@ impl PidFile {
self.is_nonblocking.load(Ordering::Relaxed)
}
pub fn process(&self) -> &Arc<Process> {
&self.process
pub fn process_opt(&self) -> Option<Arc<Process>> {
self.process.upgrade()
}
}
@ -125,17 +130,19 @@ impl FileLike for PidFile {
if fd_flags.contains(FdFlags::CLOEXEC) {
flags |= CreationFlags::O_CLOEXEC.bits();
}
let pid = self.process.upgrade().map_or(u32::MAX, |p| p.pid());
Box::new(FdInfo {
flags,
pid: self.process.pid(),
})
Box::new(FdInfo { flags, pid })
}
}
impl Pollable for PidFile {
fn poll(&self, mask: IoEvents, poller: Option<&mut PollHandle>) -> IoEvents {
self.process
let Some(process) = self.process.upgrade() else {
// The process has been reaped.
return mask & IoEvents::IN;
};
process
.pidfile_pollee
.poll_with(mask, poller, || self.check_io_events())
}

View File

@ -89,9 +89,10 @@ pub fn do_wait(
ProcessFilter::Any => true,
ProcessFilter::WithPid(pid) => child.pid() == *pid,
ProcessFilter::WithPgid(pgid) => child.pgid() == *pgid,
ProcessFilter::WithPidfd(pid_file) => {
Arc::ptr_eq(pid_file.process(), *child)
}
ProcessFilter::WithPidfd(pid_file) => match pid_file.process_opt() {
Some(process) => Arc::ptr_eq(&process, child),
None => false,
},
})
.collect::<Box<_>>();

View File

@ -69,7 +69,10 @@ fn build_proxy_from_pid_file(
check_unsupported_ns_flags(flags)?;
let target_thread = pid_file.process().main_thread();
let target_thread = pid_file
.process_opt()
.ok_or_else(|| Error::with_message(Errno::ESRCH, "the target process has been reaped"))?
.main_thread();
let target_proxy = target_thread.as_posix_thread().unwrap().ns_proxy().lock();
let Some(target_proxy) = target_proxy.as_ref() else {
return_errno_with_message!(Errno::ESRCH, "the target process has exited");