@@ -18,6 +18,7 @@ mod unsafe_list;
1818
1919use crate :: num:: NonZeroUsize ;
2020use crate :: ops:: { Deref , DerefMut } ;
21+ use crate :: panic:: { self , AssertUnwindSafe } ;
2122use crate :: time:: Duration ;
2223
2324use super :: abi:: thread;
@@ -147,9 +148,8 @@ impl WaitQueue {
147148 /// Adds the calling thread to the `WaitVariable`'s wait queue, then wait
148149 /// until a wakeup event.
149150 ///
150- /// This function does not return until this thread has been awoken.
151- ///
152- /// Safety: `before_wait` must not panic
151+ /// This function does not return until this thread has been awoken. When `before_wait` panics,
152+ /// this function will abort.
153153 pub fn wait < T , F : FnOnce ( ) > ( mut guard : SpinMutexGuard < ' _ , WaitVariable < T > > , before_wait : F ) {
154154 // very unsafe: check requirements of UnsafeList::push
155155 unsafe {
@@ -159,7 +159,9 @@ impl WaitQueue {
159159 } ) ) ;
160160 let entry = guard. queue . inner . push ( & mut entry) ;
161161 drop ( guard) ;
162- before_wait ( ) ;
162+ if let Err ( _e) = panic:: catch_unwind ( AssertUnwindSafe ( || before_wait ( ) ) ) {
163+ rtabort ! ( "Panic before wait on wakeup event" )
164+ }
163165 while !entry. lock ( ) . wake {
164166 // `entry.wake` is only set in `notify_one` and `notify_all` functions. Both ensure
165167 // the entry is removed from the queue _before_ setting this bool. There are no
@@ -174,7 +176,7 @@ impl WaitQueue {
174176 /// Adds the calling thread to the `WaitVariable`'s wait queue, then wait
175177 /// until a wakeup event or timeout. If event was observed, returns true.
176178 /// If not, it will remove the calling thread from the wait queue.
177- /// Safety: `before_wait` must not panic
179+ /// When `before_wait` panics, this function will abort.
178180 pub fn wait_timeout < T , F : FnOnce ( ) > (
179181 lock : & SpinMutex < WaitVariable < T > > ,
180182 timeout : Duration ,
@@ -187,7 +189,9 @@ impl WaitQueue {
187189 wake : false ,
188190 } ) ) ;
189191 let entry_lock = lock. lock ( ) . queue . inner . push ( & mut entry) ;
190- before_wait ( ) ;
192+ if let Err ( _e) = panic:: catch_unwind ( AssertUnwindSafe ( || before_wait ( ) ) ) {
193+ rtabort ! ( "Panic before wait on wakeup event or timeout" )
194+ }
191195 usercalls:: wait_timeout ( EV_UNPARK , timeout, || entry_lock. lock ( ) . wake ) ;
192196 // acquire the wait queue's lock first to avoid deadlock
193197 // and ensure no other function can simultaneously access the list
0 commit comments