Make FatalErrorMarker
lower priority than other panics
This commit is contained in:
parent
1d6f05fd37
commit
ff1858e2aa
@ -127,6 +127,9 @@ fn drop(&mut self) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is a marker for a fatal compiler error used with `resume_unwind`.
|
||||||
|
pub struct FatalErrorMarker;
|
||||||
|
|
||||||
/// Turns a closure that takes an `&mut Formatter` into something that can be display-formatted.
|
/// Turns a closure that takes an `&mut Formatter` into something that can be display-formatted.
|
||||||
pub fn make_display(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Display {
|
pub fn make_display(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Display {
|
||||||
struct Printer<F> {
|
struct Printer<F> {
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use crate::sync::IntoDynSyncSend;
|
||||||
|
use crate::FatalErrorMarker;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
|
use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
|
||||||
@ -18,14 +20,17 @@
|
|||||||
/// continuing with unwinding. It's also used for the non-parallel code to ensure error message
|
/// continuing with unwinding. It's also used for the non-parallel code to ensure error message
|
||||||
/// output match the parallel compiler for testing purposes.
|
/// output match the parallel compiler for testing purposes.
|
||||||
pub struct ParallelGuard {
|
pub struct ParallelGuard {
|
||||||
panic: Mutex<Option<Box<dyn Any + Send + 'static>>>,
|
panic: Mutex<Option<IntoDynSyncSend<Box<dyn Any + Send + 'static>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParallelGuard {
|
impl ParallelGuard {
|
||||||
pub fn run<R>(&self, f: impl FnOnce() -> R) -> Option<R> {
|
pub fn run<R>(&self, f: impl FnOnce() -> R) -> Option<R> {
|
||||||
catch_unwind(AssertUnwindSafe(f))
|
catch_unwind(AssertUnwindSafe(f))
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
*self.panic.lock() = Some(err);
|
let mut panic = self.panic.lock();
|
||||||
|
if panic.is_none() || !(*err).is::<FatalErrorMarker>() {
|
||||||
|
*panic = Some(IntoDynSyncSend(err));
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.ok()
|
.ok()
|
||||||
}
|
}
|
||||||
@ -37,7 +42,7 @@ pub fn run<R>(&self, f: impl FnOnce() -> R) -> Option<R> {
|
|||||||
pub fn parallel_guard<R>(f: impl FnOnce(&ParallelGuard) -> R) -> R {
|
pub fn parallel_guard<R>(f: impl FnOnce(&ParallelGuard) -> R) -> R {
|
||||||
let guard = ParallelGuard { panic: Mutex::new(None) };
|
let guard = ParallelGuard { panic: Mutex::new(None) };
|
||||||
let ret = f(&guard);
|
let ret = f(&guard);
|
||||||
if let Some(panic) = guard.panic.into_inner() {
|
if let Some(IntoDynSyncSend(panic)) = guard.panic.into_inner() {
|
||||||
resume_unwind(panic);
|
resume_unwind(panic);
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
@ -106,14 +111,20 @@ macro_rules! parallel {
|
|||||||
parallel!(impl $fblock [$block, $($c,)*] [$($rest),*])
|
parallel!(impl $fblock [$block, $($c,)*] [$($rest),*])
|
||||||
};
|
};
|
||||||
(impl $fblock:block [$($blocks:expr,)*] []) => {
|
(impl $fblock:block [$($blocks:expr,)*] []) => {
|
||||||
::rustc_data_structures::sync::scope(|s| {
|
$crate::sync::parallel_guard(|guard| {
|
||||||
$(let block = rustc_data_structures::sync::FromDyn::from(|| $blocks);
|
$crate::sync::scope(|s| {
|
||||||
s.spawn(move |_| block.into_inner()());)*
|
$(
|
||||||
(|| $fblock)();
|
let block = $crate::sync::FromDyn::from(|| $blocks);
|
||||||
|
s.spawn(move |_| {
|
||||||
|
guard.run(move || block.into_inner()());
|
||||||
|
});
|
||||||
|
)*
|
||||||
|
guard.run(|| $fblock);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
($fblock:block, $($blocks:block),*) => {
|
($fblock:block, $($blocks:block),*) => {
|
||||||
if rustc_data_structures::sync::is_dyn_thread_safe() {
|
if $crate::sync::is_dyn_thread_safe() {
|
||||||
// Reverse the order of the later blocks since Rayon executes them in reverse order
|
// Reverse the order of the later blocks since Rayon executes them in reverse order
|
||||||
// when using a single thread. This ensures the execution order matches that
|
// when using a single thread. This ensures the execution order matches that
|
||||||
// of a single threaded rustc.
|
// of a single threaded rustc.
|
||||||
@ -146,11 +157,13 @@ pub fn join<A, B, RA: DynSend, RB: DynSend>(oper_a: A, oper_b: B) -> (RA, RB)
|
|||||||
if mode::is_dyn_thread_safe() {
|
if mode::is_dyn_thread_safe() {
|
||||||
let oper_a = FromDyn::from(oper_a);
|
let oper_a = FromDyn::from(oper_a);
|
||||||
let oper_b = FromDyn::from(oper_b);
|
let oper_b = FromDyn::from(oper_b);
|
||||||
let (a, b) = rayon::join(
|
let (a, b) = parallel_guard(|guard| {
|
||||||
move || FromDyn::from(oper_a.into_inner()()),
|
rayon::join(
|
||||||
move || FromDyn::from(oper_b.into_inner()()),
|
move || guard.run(move || FromDyn::from(oper_a.into_inner()())),
|
||||||
);
|
move || guard.run(move || FromDyn::from(oper_b.into_inner()())),
|
||||||
(a.into_inner(), b.into_inner())
|
)
|
||||||
|
});
|
||||||
|
(a.unwrap().into_inner(), b.unwrap().into_inner())
|
||||||
} else {
|
} else {
|
||||||
super::disabled::join(oper_a, oper_b)
|
super::disabled::join(oper_a, oper_b)
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct FatalError;
|
pub struct FatalError;
|
||||||
|
|
||||||
pub struct FatalErrorMarker;
|
pub use rustc_data_structures::FatalErrorMarker;
|
||||||
|
|
||||||
// Don't implement Send on FatalError. This makes it impossible to panic!(FatalError).
|
// Don't implement Send on FatalError. This makes it impossible to panic!(FatalError).
|
||||||
// We don't want to invoke the panic handler and print a backtrace for fatal errors.
|
// We don't want to invoke the panic handler and print a backtrace for fatal errors.
|
||||||
|
Loading…
Reference in New Issue
Block a user