@@ -499,13 +499,40 @@ impl Builder {
499499 let output_capture = crate :: io:: set_output_capture ( None ) ;
500500 crate :: io:: set_output_capture ( output_capture. clone ( ) ) ;
501501
502+ // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*.
503+ // See <https://github.com/rust-lang/rust/issues/101983> for more details.
504+ // To prevent leaks we use a wrapper that drops its contents.
505+ #[ repr( transparent) ]
506+ struct MaybeDangling < T > ( mem:: MaybeUninit < T > ) ;
507+ impl < T > MaybeDangling < T > {
508+ fn new ( x : T ) -> Self {
509+ MaybeDangling ( mem:: MaybeUninit :: new ( x) )
510+ }
511+ fn into_inner ( self ) -> T {
512+ // SAFETY: we are always initiailized.
513+ let ret = unsafe { self . 0 . assume_init_read ( ) } ;
514+ // Make sure we don't drop.
515+ mem:: forget ( self ) ;
516+ ret
517+ }
518+ }
519+ impl < T > Drop for MaybeDangling < T > {
520+ fn drop ( & mut self ) {
521+ // SAFETY: we are always initiailized.
522+ unsafe { self . 0 . assume_init_drop ( ) } ;
523+ }
524+ }
525+
526+ let f = MaybeDangling :: new ( f) ;
502527 let main = move || {
503528 if let Some ( name) = their_thread. cname ( ) {
504529 imp:: Thread :: set_name ( name) ;
505530 }
506531
507532 crate :: io:: set_output_capture ( output_capture) ;
508533
534+ // SAFETY: we constructed `f` initialized.
535+ let f = f. into_inner ( ) ;
509536 // SAFETY: the stack guard passed is the one for the current thread.
510537 // This means the current thread's stack and the new thread's stack
511538 // are properly set and protected from each other.
@@ -518,6 +545,12 @@ impl Builder {
518545 // same `JoinInner` as this closure meaning the mutation will be
519546 // safe (not modify it and affect a value far away).
520547 unsafe { * their_packet. result . get ( ) = Some ( try_result) } ;
548+ // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that
549+ // will call `decrement_num_running_threads` and therefore signal that this thread is
550+ // done.
551+ drop ( their_packet) ;
552+ // Here, the lifetime `'a` and even `'scope` can end. `main` keeps running for a bit
553+ // after that before returning itself.
521554 } ;
522555
523556 if let Some ( scope_data) = & my_packet. scope {
0 commit comments