@@ -111,6 +111,8 @@ where
111
111
}
112
112
113
113
pub ( super ) fn drop_join_handle_slow ( self ) {
114
+ let mut maybe_panic = None ;
115
+
114
116
// Try to unset `JOIN_INTEREST`. This must be done as a first step in
115
117
// case the task concurrently completed.
116
118
if self . header ( ) . state . unset_join_interested ( ) . is_err ( ) {
@@ -119,11 +121,20 @@ where
119
121
// the scheduler or `JoinHandle`. i.e. if the output remains in the
120
122
// task structure until the task is deallocated, it may be dropped
121
123
// by a Waker on any arbitrary thread.
122
- self . core ( ) . stage . drop_future_or_output ( ) ;
124
+ let panic = panic:: catch_unwind ( panic:: AssertUnwindSafe ( || {
125
+ self . core ( ) . stage . drop_future_or_output ( ) ;
126
+ } ) ) ;
127
+ if let Err ( panic) = panic {
128
+ maybe_panic = Some ( panic) ;
129
+ }
123
130
}
124
131
125
132
// Drop the `JoinHandle` reference, possibly deallocating the task
126
133
self . drop_reference ( ) ;
134
+
135
+ if let Some ( panic) = maybe_panic {
136
+ panic:: resume_unwind ( panic) ;
137
+ }
127
138
}
128
139
129
140
// ===== waker behavior =====
@@ -182,17 +193,25 @@ where
182
193
// ====== internal ======
183
194
184
195
fn complete ( self , output : super :: Result < T :: Output > , is_join_interested : bool ) {
185
- if is_join_interested {
186
- // Store the output. The future has already been dropped
187
- //
188
- // Safety: Mutual exclusion is obtained by having transitioned the task
189
- // state -> Running
190
- let stage = & self . core ( ) . stage ;
191
- stage. store_output ( output) ;
192
-
193
- // Transition to `Complete`, notifying the `JoinHandle` if necessary.
194
- transition_to_complete ( self . header ( ) , stage, & self . trailer ( ) ) ;
195
- }
196
+ // We catch panics here because dropping the output may panic.
197
+ //
198
+ // Dropping the output can also happen in the first branch inside
199
+ // transition_to_complete.
200
+ let _ = panic:: catch_unwind ( panic:: AssertUnwindSafe ( || {
201
+ if is_join_interested {
202
+ // Store the output. The future has already been dropped
203
+ //
204
+ // Safety: Mutual exclusion is obtained by having transitioned the task
205
+ // state -> Running
206
+ let stage = & self . core ( ) . stage ;
207
+ stage. store_output ( output) ;
208
+
209
+ // Transition to `Complete`, notifying the `JoinHandle` if necessary.
210
+ transition_to_complete ( self . header ( ) , stage, & self . trailer ( ) ) ;
211
+ } else {
212
+ drop ( output) ;
213
+ }
214
+ } ) ) ;
196
215
197
216
// The task has completed execution and will no longer be scheduled.
198
217
//
0 commit comments