@@ -18,6 +18,7 @@ mod unsafe_list;
18
18
19
19
use crate :: num:: NonZeroUsize ;
20
20
use crate :: ops:: { Deref , DerefMut } ;
21
+ use crate :: panic:: { self , AssertUnwindSafe } ;
21
22
use crate :: time:: Duration ;
22
23
23
24
use super :: abi:: thread;
@@ -147,9 +148,8 @@ impl WaitQueue {
147
148
/// Adds the calling thread to the `WaitVariable`'s wait queue, then wait
148
149
/// until a wakeup event.
149
150
///
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.
153
153
pub fn wait < T , F : FnOnce ( ) > ( mut guard : SpinMutexGuard < ' _ , WaitVariable < T > > , before_wait : F ) {
154
154
// very unsafe: check requirements of UnsafeList::push
155
155
unsafe {
@@ -159,7 +159,9 @@ impl WaitQueue {
159
159
} ) ) ;
160
160
let entry = guard. queue . inner . push ( & mut entry) ;
161
161
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
+ }
163
165
while !entry. lock ( ) . wake {
164
166
// `entry.wake` is only set in `notify_one` and `notify_all` functions. Both ensure
165
167
// the entry is removed from the queue _before_ setting this bool. There are no
@@ -174,7 +176,7 @@ impl WaitQueue {
174
176
/// Adds the calling thread to the `WaitVariable`'s wait queue, then wait
175
177
/// until a wakeup event or timeout. If event was observed, returns true.
176
178
/// 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.
178
180
pub fn wait_timeout < T , F : FnOnce ( ) > (
179
181
lock : & SpinMutex < WaitVariable < T > > ,
180
182
timeout : Duration ,
@@ -187,7 +189,9 @@ impl WaitQueue {
187
189
wake : false ,
188
190
} ) ) ;
189
191
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
+ }
191
195
usercalls:: wait_timeout ( EV_UNPARK , timeout, || entry_lock. lock ( ) . wake ) ;
192
196
// acquire the wait queue's lock first to avoid deadlock
193
197
// and ensure no other function can simultaneously access the list
0 commit comments