From 437f76233908faa67eb45c7b00e6494d68345de3 Mon Sep 17 00:00:00 2001 From: Wildan M Date: Fri, 27 Feb 2026 12:34:13 +0700 Subject: [PATCH] Prevent drop on WaitCondition --- src/event.rs | 4 ++++ src/scheme/event.rs | 9 ++++++--- src/scheme/mod.rs | 15 +++++++++++---- src/scheme/pipe.rs | 23 ++++++++++++++++++++++- src/scheme/user.rs | 4 ++++ src/sync/wait_condition.rs | 22 ++++++++++++++++++---- 6 files changed, 65 insertions(+), 12 deletions(-) diff --git a/src/event.rs b/src/event.rs index 1e11f32d12..64695b26f8 100644 --- a/src/event.rs +++ b/src/event.rs @@ -85,6 +85,10 @@ impl EventQueue { Ok(events.len()) } + + pub fn into_drop(self, token: &mut CleanLockToken) { + self.queue.condition.into_drop(token); + } } pub type EventQueueList = HashMap>; diff --git a/src/scheme/event.rs b/src/scheme/event.rs index 4dbfcfe286..7f111ec5de 100644 --- a/src/scheme/event.rs +++ b/src/scheme/event.rs @@ -43,10 +43,13 @@ impl KernelScheme for EventScheme { fn close(&self, id: usize, token: &mut CleanLockToken) -> Result<()> { let id = EventQueueId::from(id); - queues_mut(token.token()) + let queue = queues_mut(token.token()) .remove(&id) - .ok_or(Error::new(EBADF)) - .and(Ok(())) + .ok_or(Error::new(EBADF))?; + if let Some(queue) = Arc::into_inner(queue) { + queue.into_drop(token); + } + Ok(()) } fn kread( diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs index 2e1d2050e7..92b459fb62 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -225,10 +225,17 @@ impl SchemeList { /// Remove a scheme fn remove(&self, id: usize, token: &mut CleanLockToken) { - assert!(handles() - .write(token.token()) - .remove(&SchemeId(id)) - .is_some()); + let scheme = handles().write(token.token()).remove(&SchemeId(id)); + + assert!(scheme.is_some()); + match scheme { + Some(Handle::Scheme(KernelSchemes::User(user))) => { + if let Some(user) = Arc::into_inner(user.inner) { + user.into_drop(token); + } + } + _ => {} + } } } diff --git a/src/scheme/pipe.rs b/src/scheme/pipe.rs index e2128f89e3..7d3c3ae9e4 100644 --- a/src/scheme/pipe.rs +++ b/src/scheme/pipe.rs @@ -136,7 +136,28 @@ impl KernelScheme for PipeScheme { }; if can_remove { - let _ = PIPES.write(token.token()).remove(&key); + match { PIPES.write(token.token()).remove(&key) } { + Some(Handle::Pipe(pipe)) => { + if let Some(pipe) = Arc::into_inner(pipe) { + { + pipe.read_condition.into_drop(token); + } + { + pipe.write_condition.into_drop(token); + } + } + } + _ => {} + } + } + + if let Some(pipe) = Arc::into_inner(pipe) { + { + pipe.read_condition.into_drop(token); + } + { + pipe.write_condition.into_drop(token); + } } Ok(()) diff --git a/src/scheme/user.rs b/src/scheme/user.rs index 940124e27b..9f1d1350df 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -1260,6 +1260,10 @@ impl UserInner { Ok(num_fds) } + + pub fn into_drop(self, token: &mut CleanLockToken) { + self.todo.condition.into_drop(token); + } } pub struct CaptureGuard { destroyed: bool, diff --git a/src/sync/wait_condition.rs b/src/sync/wait_condition.rs index 15e8b155c6..47df00a5dd 100644 --- a/src/sync/wait_condition.rs +++ b/src/sync/wait_condition.rs @@ -1,3 +1,5 @@ +use core::mem::ManuallyDrop; + use alloc::{ sync::{Arc, Weak}, vec::Vec, @@ -124,14 +126,26 @@ impl WaitCondition { waited } + + pub fn into_drop(mut self, token: &mut CleanLockToken) { + ManuallyDrop::new(self).inner_drop(token); + } + + fn inner_drop(&mut self, token: &mut CleanLockToken) { + unsafe { + self.notify_signal(token); + } + } } impl Drop for WaitCondition { fn drop(&mut self) { //TODO: drop violates lock tokens - unsafe { - let mut token = CleanLockToken::new(); - self.notify_signal(&mut token); - }; + let mut token = unsafe { CleanLockToken::new() }; + self.inner_drop(&mut token); + #[cfg(feature = "drop_panic")] + { + panic!("WaitCondition dropped"); + } } }