@@ -133,6 +133,13 @@ impl<F: Future + 'static> TaskAlloc<F> {
133133 }
134134
135135 unsafe fn drop_future ( header : NonNull < Header > , has_result : bool ) {
136+ // The future/result types are unwind-unsafe (ManuallyDrop, union).
137+ // Dropping them during an existing panic could trigger a second panic,
138+ // which would be UB. Instead, leak the contents during unwinding.
139+ if :: std:: thread:: panicking ( ) {
140+ return ;
141+ }
142+
136143 let future_cell = Self :: future_cell ( header) ;
137144
138145 future_cell. with_mut ( |fut_ptr| {
@@ -298,6 +305,13 @@ impl Task {
298305
299306 header. shared . store ( ptr:: null_mut ( ) , Release ) ;
300307
308+ // Dropping the future/result and waker during unwinding on unwind-unsafe
309+ // types could trigger a second panic. Skip content drops if already panicking.
310+ if :: std:: thread:: panicking ( ) {
311+ trace ! ( "Skipping content drops during panic" ) ;
312+ return ;
313+ }
314+
301315 if !state. is_completed ( ) {
302316 trace ! ( "Dropping future" ) ;
303317 // The task has not completed yet, drop future
@@ -361,6 +375,16 @@ impl Drop for Task {
361375 return ;
362376 } ;
363377
378+ // The future/result and waker types are unwind-unsafe (ManuallyDrop in
379+ // union, MaybeUninit). Dropping them during an existing panic could
380+ // trigger a second panic, which would be UB. Skip content drops but
381+ // still deallocate the memory since dealloc does not run destructors
382+ // on the inner types.
383+ if :: std:: thread:: panicking ( ) {
384+ unsafe { ( header. vtable . dealloc ) ( self . 0 ) }
385+ return ;
386+ }
387+
364388 crate :: panic_guard!( ) ;
365389
366390 debug_assert ! ( state. is_completed( ) | state. is_cancelled( ) ) ;
0 commit comments