mirror of
https://github.com/servo/servo.git
synced 2025-07-17 20:33:40 +01:00
Improve winit/mach segfault output
This commit is contained in:
parent
6fe87c985b
commit
07c1286334
2 changed files with 34 additions and 9 deletions
|
@ -8,24 +8,46 @@ pub fn install() {}
|
||||||
#[cfg(any(target_os = "macos", target_os = "linux"))]
|
#[cfg(any(target_os = "macos", target_os = "linux"))]
|
||||||
pub fn install() {
|
pub fn install() {
|
||||||
use crate::backtrace;
|
use crate::backtrace;
|
||||||
use libc::_exit;
|
|
||||||
use sig::ffi::Sig;
|
use sig::ffi::Sig;
|
||||||
use std::{io::Write, sync::atomic, thread};
|
use std::{io::Write, sync::atomic, thread};
|
||||||
|
|
||||||
extern "C" fn handler(sig: i32) {
|
extern "C" fn handler(sig: i32) {
|
||||||
|
// Only print crash message and backtrace the first time, to avoid
|
||||||
|
// infinite recursion if the printing causes another signal.
|
||||||
static BEEN_HERE_BEFORE: atomic::AtomicBool = atomic::AtomicBool::new(false);
|
static BEEN_HERE_BEFORE: atomic::AtomicBool = atomic::AtomicBool::new(false);
|
||||||
if !BEEN_HERE_BEFORE.swap(true, atomic::Ordering::SeqCst) {
|
if !BEEN_HERE_BEFORE.swap(true, atomic::Ordering::SeqCst) {
|
||||||
let stdout = std::io::stdout();
|
// stderr is unbuffered, so we won’t lose output if we crash later
|
||||||
let mut stdout = stdout.lock();
|
// in this handler, and the std::io::stderr() call never allocates.
|
||||||
let _ = write!(&mut stdout, "Stack trace");
|
// std::io::stdout() allocates the first time it’s called, which in
|
||||||
|
// practice will often segfault (see below).
|
||||||
|
let stderr = std::io::stderr();
|
||||||
|
let mut stderr = stderr.lock();
|
||||||
|
let _ = write!(&mut stderr, "Caught signal {sig}");
|
||||||
if let Some(name) = thread::current().name() {
|
if let Some(name) = thread::current().name() {
|
||||||
let _ = write!(&mut stdout, " for thread \"{}\"", name);
|
let _ = write!(&mut stderr, " in thread \"{}\"", name);
|
||||||
}
|
}
|
||||||
let _ = write!(&mut stdout, "\n");
|
let _ = write!(&mut stderr, "\n");
|
||||||
let _ = backtrace::print(&mut stdout);
|
|
||||||
|
// This call always allocates, which in practice will segfault if
|
||||||
|
// we’re handling a non-main-thread (e.g. layout) segfault. Strictly
|
||||||
|
// speaking in POSIX terms, this is also undefined behaviour.
|
||||||
|
let _ = backtrace::print(&mut stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Outside the BEEN_HERE_BEFORE check, we must only call functions we
|
||||||
|
// know to be “async-signal-safe”, which includes sigaction(), raise(),
|
||||||
|
// and _exit(), but generally doesn’t include anything that allocates.
|
||||||
|
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03_03
|
||||||
unsafe {
|
unsafe {
|
||||||
_exit(sig);
|
// Reset the signal to the default action, and reraise the signal.
|
||||||
|
// Unlike libc::_exit(sig), which terminates the process normally,
|
||||||
|
// this terminates abnormally just like an uncaught signal, allowing
|
||||||
|
// mach (or your shell) to distinguish it from an ordinary exit, and
|
||||||
|
// allows your kernel to make a core dump if configured to do so.
|
||||||
|
let mut action: libc::sigaction = std::mem::zeroed();
|
||||||
|
action.sa_sigaction = libc::SIG_DFL;
|
||||||
|
libc::sigaction(sig, &action, std::ptr::null_mut());
|
||||||
|
libc::raise(sig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -169,7 +169,10 @@ class PostBuildCommands(CommandBase):
|
||||||
try:
|
try:
|
||||||
check_call(args, env=env)
|
check_call(args, env=env)
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
print("Servo exited with return value %d" % e.returncode)
|
if e.returncode < 0:
|
||||||
|
print(f"Servo was terminated by signal {-e.returncode}")
|
||||||
|
else:
|
||||||
|
print(f"Servo exited with non-zero status {e.returncode}")
|
||||||
return e.returncode
|
return e.returncode
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno == 2:
|
if e.errno == 2:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue