From f58fb66cba124dce8ae6b2d3b80ff4b9c98e0531 Mon Sep 17 00:00:00 2001 From: li041 Date: Tue, 13 Jan 2026 08:15:52 +0000 Subject: [PATCH] Refactor `PidFile` to use `Weak` --- kernel/src/process/pid_file.rs | 29 ++++++++++++++++++----------- kernel/src/process/wait.rs | 7 ++++--- kernel/src/syscall/setns.rs | 5 ++++- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/kernel/src/process/pid_file.rs b/kernel/src/process/pid_file.rs index 11a34bfb9..d9611291e 100644 --- a/kernel/src/process/pid_file.rs +++ b/kernel/src/process/pid_file.rs @@ -22,7 +22,7 @@ use crate::{ }; pub struct PidFile { - process: Arc, + process: Weak, 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: . - 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 { - &self.process + pub fn process_opt(&self) -> Option> { + 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()) } diff --git a/kernel/src/process/wait.rs b/kernel/src/process/wait.rs index 309a844e2..c9bc2789c 100644 --- a/kernel/src/process/wait.rs +++ b/kernel/src/process/wait.rs @@ -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::>(); diff --git a/kernel/src/syscall/setns.rs b/kernel/src/syscall/setns.rs index d3aade871..e6bdf7f86 100644 --- a/kernel/src/syscall/setns.rs +++ b/kernel/src/syscall/setns.rs @@ -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");