servo/ports/servoshell/crash_handler.rs
Jonathan Schwender 09684a3501
Fix various clippy warnings on OpenHarmony (#34281)
* ohos: Fix more clippy warnings

Signed-off-by: Jonathan Schwender <jonathan.schwender@huawei.com>
Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>

* Remove unnecessary `macro_use`

We can use `use` instead. Removes a warning about
unused macro_use on OpenHarmony.

Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>

---------

Signed-off-by: Jonathan Schwender <jonathan.schwender@huawei.com>
Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
2024-11-19 05:21:48 +00:00

72 lines
3.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "android")))]
pub fn install() {}
#[cfg(any(target_os = "macos", target_os = "linux"))]
pub fn install() {
use std::io::Write;
use std::sync::atomic;
use std::thread;
use sig::signal;
use crate::backtrace;
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);
if !BEEN_HERE_BEFORE.swap(true, atomic::Ordering::SeqCst) {
// stderr is unbuffered, so we wont lose output if we crash later
// in this handler, and the std::io::stderr() call never allocates.
// std::io::stdout() allocates the first time its 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() {
let _ = write!(&mut stderr, " in thread \"{}\"", name);
}
let _ = writeln!(&mut stderr);
// This call always allocates, which in practice will segfault if
// were 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 doesnt include anything that allocates.
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03_03
raise_signal_or_exit_with_error(sig);
}
signal!(libc::SIGSEGV, handler); // handle segfaults
signal!(libc::SIGILL, handler); // handle stack overflow and unsupported CPUs
signal!(libc::SIGIOT, handler); // handle double panics
signal!(libc::SIGBUS, handler); // handle invalid memory access
}
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "android")))]
pub(crate) fn raise_signal_or_exit_with_error(_signal: i32) {
std::process::exit(1);
}
#[cfg(any(target_os = "macos", target_os = "linux"))]
pub(crate) fn raise_signal_or_exit_with_error(signal: i32) {
unsafe {
// 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(signal, &action, std::ptr::null_mut());
libc::raise(signal);
}
}