mirror of
https://github.com/servo/servo.git
synced 2025-10-04 02:29:12 +01:00
This fixes many rustdoc errors that occur due to raw URLs in rustdoc comments as well as unescaped Rust code that should be in backticks.
106 lines
3.5 KiB
Rust
106 lines
3.5 KiB
Rust
/* 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/. */
|
||
|
||
//! Similar to `println!("{:?}", Backtrace::new())`, but doesn’t allocate.
|
||
//!
|
||
//! Seems to fix some deadlocks: <https://github.com/servo/servo/issues/24881>
|
||
//!
|
||
//! FIXME: if/when a future version of the `backtrace` crate has
|
||
//! <https://github.com/rust-lang/backtrace-rs/pull/265>, use that instead.
|
||
|
||
use std::fmt::{self, Write};
|
||
|
||
use backtrace::{BytesOrWideString, PrintFmt};
|
||
|
||
#[inline(never)]
|
||
pub(crate) fn print(w: &mut dyn std::io::Write) -> Result<(), std::io::Error> {
|
||
write!(
|
||
w,
|
||
"{:?}",
|
||
Print {
|
||
print_fn_address: print as usize,
|
||
}
|
||
)
|
||
}
|
||
|
||
struct Print {
|
||
print_fn_address: usize,
|
||
}
|
||
|
||
impl fmt::Debug for Print {
|
||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||
// 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
|
||
});
|
||
|
||
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;
|
||
}
|
||
|
||
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()
|
||
}
|
||
}
|
||
}
|
||
|
||
fn print_path(fmt: &mut fmt::Formatter<'_>, path: BytesOrWideString<'_>) -> fmt::Result {
|
||
match path {
|
||
BytesOrWideString::Bytes(mut bytes) => loop {
|
||
match std::str::from_utf8(bytes) {
|
||
Ok(s) => {
|
||
fmt.write_str(s)?;
|
||
break;
|
||
},
|
||
Err(err) => {
|
||
fmt.write_char(std::char::REPLACEMENT_CHARACTER)?;
|
||
match err.error_len() {
|
||
Some(len) => bytes = &bytes[err.valid_up_to() + len..],
|
||
None => break,
|
||
}
|
||
},
|
||
}
|
||
},
|
||
BytesOrWideString::Wide(wide) => {
|
||
for c in std::char::decode_utf16(wide.iter().cloned()) {
|
||
fmt.write_char(c.unwrap_or(std::char::REPLACEMENT_CHARACTER))?
|
||
}
|
||
},
|
||
}
|
||
Ok(())
|
||
}
|