@@ -182,14 +182,37 @@ impl Builder {
182182 let f = f. clone ( ) ;
183183
184184 scheduler. run ( & mut execution, move || {
185- f ( ) ;
185+ /// the given closure `f` may panic when executed.
186+ /// when this happens, we still want to ensure
187+ /// that thread locals are destructed before the
188+ /// global statics are dropped. therefore, we set
189+ /// up a guard that is dropped as part of the unwind
190+ /// logic when `f` panics. this guard in turn ensures,
191+ /// through the implementation of `rt::thread_done`,
192+ /// that thread local fields are dropped before the
193+ /// global statics are dropped. without this guard,
194+ /// a `Drop` implementation on a type that is stored
195+ /// in a thread local field could access the lazy static,
196+ /// and this then would in turn panic from the method
197+ /// [`Lazy::get`](crate::lazy_static::Lazy), which
198+ /// causes a panic inside a panic, which in turn causes
199+ /// Rust to abort, triggering a segfault in `loom`.
200+ struct PanicGuard ;
201+ impl Drop for PanicGuard {
202+ fn drop ( & mut self ) {
203+ rt:: thread_done ( true ) ;
204+ }
205+ }
186206
187- let lazy_statics = rt:: execution ( |execution| execution. lazy_statics . drop ( ) ) ;
207+ // set up the panic guard
208+ let panic_guard = PanicGuard ;
188209
189- // drop outside of execution
190- drop ( lazy_statics ) ;
210+ // execute the closure, note that `f()` may panic!
211+ f ( ) ;
191212
192- rt:: thread_done ( ) ;
213+ // if `f()` didn't panic, then we terminate the
214+ // main thread by dropping the guard ourselves.
215+ drop ( panic_guard) ;
193216 } ) ;
194217
195218 execution. check_for_leaks ( ) ;
0 commit comments