From 5bcd2f564297aacc04189fd6001c0ab0b03ffad2 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 27 Nov 2019 21:10:18 +0100 Subject: [PATCH] Avoid locking in the signal handler --- ports/glutin/backtrace.rs | 81 +++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/ports/glutin/backtrace.rs b/ports/glutin/backtrace.rs index 0c089336557..6e5a8390042 100644 --- a/ports/glutin/backtrace.rs +++ b/ports/glutin/backtrace.rs @@ -25,47 +25,52 @@ struct Print { impl fmt::Debug for Print { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - let mut print_fn_frame = 0; - let mut frame_count = 0; - backtrace::trace(|frame| { - let found = frame.symbol_address() as usize == self.print_fn_address; - if found { - print_fn_frame = frame_count; - } - frame_count += 1; - !found - }); - - let mode = PrintFmt::Short; - let mut p = print_path; - let mut f = backtrace::BacktraceFmt::new(fmt, mode, &mut p); - f.add_context()?; - let mut result = Ok(()); - let mut frame_count = 0; - backtrace::trace(|frame| { - let skip = frame_count < print_fn_frame; - frame_count += 1; - if skip { - return true - } - - let mut frame_fmt = f.frame(); - let mut any_symbol = false; - backtrace::resolve_frame(frame, |symbol| { - any_symbol = true; - if let Err(e) = frame_fmt.symbol(frame, symbol) { - result = Err(e) + // Safety: we’re in a signal handler that is about to call `libc::_exit`. + // Potential data races from using `*_unsynchronized` functions are perhaps + // less bad than potential deadlocks? + unsafe { + let mut print_fn_frame = 0; + let mut frame_count = 0; + backtrace::trace_unsynchronized(|frame| { + let found = frame.symbol_address() as usize == self.print_fn_address; + if found { + print_fn_frame = frame_count; } + frame_count += 1; + !found }); - if !any_symbol { - if let Err(e) = frame_fmt.print_raw(frame.ip(), None, None, None) { - result = Err(e) + + let mode = PrintFmt::Short; + let mut p = print_path; + let mut f = backtrace::BacktraceFmt::new(fmt, mode, &mut p); + f.add_context()?; + let mut result = Ok(()); + let mut frame_count = 0; + backtrace::trace_unsynchronized(|frame| { + let skip = frame_count < print_fn_frame; + frame_count += 1; + if skip { + return true } - } - result.is_ok() - }); - result?; - f.finish() + + let mut frame_fmt = f.frame(); + let mut any_symbol = false; + backtrace::resolve_frame_unsynchronized(frame, |symbol| { + any_symbol = true; + if let Err(e) = frame_fmt.symbol(frame, symbol) { + result = Err(e) + } + }); + if !any_symbol { + if let Err(e) = frame_fmt.print_raw(frame.ip(), None, None, None) { + result = Err(e) + } + } + result.is_ok() + }); + result?; + f.finish() + } } }