servoshell/
panic_hook.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::io::Write;
6use std::panic::PanicHookInfo;
7use std::{env, thread};
8
9use log::{error, warn};
10use servo::config::opts;
11
12use crate::crash_handler::raise_signal_or_exit_with_error;
13
14pub(crate) fn panic_hook(info: &PanicHookInfo) {
15    warn!("Panic hook called.");
16    let msg = match info.payload().downcast_ref::<&'static str>() {
17        Some(s) => *s,
18        None => match info.payload().downcast_ref::<String>() {
19            Some(s) => &**s,
20            None => "Box<Any>",
21        },
22    };
23    let current_thread = thread::current();
24    let name = current_thread.name().unwrap_or("<unnamed>");
25    let stderr = std::io::stderr();
26    let mut stderr = stderr.lock();
27    if let Some(location) = info.location() {
28        let _ = writeln!(
29            &mut stderr,
30            "{} (thread {}, at {}:{})",
31            msg,
32            name,
33            location.file(),
34            location.line()
35        );
36    } else {
37        let _ = writeln!(&mut stderr, "{} (thread {})", msg, name);
38    }
39    if env::var("RUST_BACKTRACE").is_ok() {
40        let _ = crate::backtrace::print(&mut stderr);
41    }
42    drop(stderr);
43
44    // TODO: This shouldn't be using internal Servo options here. Perhaps this functionality should
45    // move into libservo itself.
46    if opts::get().hard_fail && !opts::get().multiprocess {
47        // When we are exiting due to a hard-failure mode, we trigger a segfault so that crash
48        // tests detect that we crashed. If we exit normally it just looks like a non-crash exit.
49        raise_signal_or_exit_with_error(libc::SIGSEGV);
50    }
51
52    error!("{}", msg);
53}