Skip to content

Commit c9e046b

Browse files
udesouqinsoon
andauthored
Porting "Abort for GC thread panic" to master (#223)
Porting #221 to `master`. Co-authored-by: Yi Lin <[email protected]>
1 parent 2310eba commit c9e046b

File tree

3 files changed

+79
-11
lines changed

3 files changed

+79
-11
lines changed

mmtk/src/api.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ pub extern "C" fn mmtk_gc_init(
104104
// Make sure we initialize MMTk here
105105
lazy_static::initialize(&SINGLETON);
106106

107+
// Hijack the panic hook to make sure that if we crash in the GC threads, the process aborts.
108+
crate::set_panic_hook();
109+
107110
// Assert to make sure our fastpath allocation is correct.
108111
{
109112
// If the assertion failed, check the allocation fastpath in Julia

mmtk/src/collection.rs

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,27 @@ use crate::{BLOCK_FOR_GC, STW_COND, WORLD_HAS_STOPPED};
1616

1717
pub static GC_START: AtomicU64 = AtomicU64::new(0);
1818

19+
use std::collections::HashSet;
20+
use std::sync::RwLock;
21+
use std::thread::ThreadId;
22+
23+
lazy_static! {
24+
static ref GC_THREADS: RwLock<HashSet<ThreadId>> = RwLock::new(HashSet::new());
25+
}
26+
27+
pub(crate) fn register_gc_thread() {
28+
let id = std::thread::current().id();
29+
GC_THREADS.write().unwrap().insert(id);
30+
}
31+
pub(crate) fn unregister_gc_thread() {
32+
let id = std::thread::current().id();
33+
GC_THREADS.write().unwrap().remove(&id);
34+
}
35+
pub(crate) fn is_gc_thread() -> bool {
36+
let id = std::thread::current().id();
37+
GC_THREADS.read().unwrap().contains(&id)
38+
}
39+
1940
pub struct VMCollection {}
2041

2142
impl Collection<JuliaVM> for VMCollection {
@@ -84,18 +105,28 @@ impl Collection<JuliaVM> for VMCollection {
84105

85106
fn spawn_gc_thread(_tls: VMThread, ctx: GCThreadContext<JuliaVM>) {
86107
// Just drop the join handle. The thread will run until the process quits.
87-
let _ = std::thread::spawn(move || {
88-
use mmtk::util::opaque_pointer::*;
89-
use mmtk::util::Address;
90-
let worker_tls = VMWorkerThread(VMThread(OpaquePointer::from_address(unsafe {
91-
Address::from_usize(thread_id::get())
92-
})));
93-
match ctx {
94-
GCThreadContext::Worker(w) => {
95-
mmtk::memory_manager::start_worker(&SINGLETON, worker_tls, w)
108+
let _ = std::thread::Builder::new()
109+
.name("MMTk Worker".to_string())
110+
.spawn(move || {
111+
use mmtk::util::opaque_pointer::*;
112+
use mmtk::util::Address;
113+
114+
// Remember this GC thread
115+
register_gc_thread();
116+
117+
// Start the worker loop
118+
let worker_tls = VMWorkerThread(VMThread(OpaquePointer::from_address(unsafe {
119+
Address::from_usize(thread_id::get())
120+
})));
121+
match ctx {
122+
GCThreadContext::Worker(w) => {
123+
mmtk::memory_manager::start_worker(&SINGLETON, worker_tls, w)
124+
}
96125
}
97-
}
98-
});
126+
127+
// The GC thread quits somehow. Unresgister this GC thread
128+
unregister_gc_thread();
129+
});
99130
}
100131

101132
fn schedule_finalization(_tls: VMWorkerThread) {}

mmtk/src/lib.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,37 @@ extern "C" {
121121
pub fn jl_gc_genericmemory_how(m: Address) -> usize;
122122
pub fn jl_gc_get_max_memory() -> usize;
123123
}
124+
125+
pub(crate) fn set_panic_hook() {
126+
let old_hook = std::panic::take_hook();
127+
128+
std::panic::set_hook(Box::new(move |panic_info| {
129+
if crate::collection::is_gc_thread() {
130+
eprintln!("ERROR: An MMTk GC thread panicked. This is a bug.");
131+
eprintln!("{panic_info}");
132+
133+
let bt = std::backtrace::Backtrace::capture();
134+
match bt.status() {
135+
std::backtrace::BacktraceStatus::Unsupported => {
136+
eprintln!("Backtrace is unsupported.")
137+
}
138+
std::backtrace::BacktraceStatus::Disabled => {
139+
eprintln!("Backtrace is disabled.");
140+
eprintln!(
141+
"run with `RUST_BACKTRACE=1` environment variable to display a backtrace"
142+
);
143+
}
144+
std::backtrace::BacktraceStatus::Captured => {
145+
eprintln!("{bt}");
146+
}
147+
s => {
148+
eprintln!("Unknown backtrace status: {s:?}");
149+
}
150+
}
151+
152+
std::process::abort();
153+
} else {
154+
old_hook(panic_info);
155+
}
156+
}));
157+
}

0 commit comments

Comments
 (0)