Skip to content

Commit 60d9b10

Browse files
peterzhu2118matzbot
authored andcommitted
[ruby/mmtk] Propagate crash of GC thread to mutator thread
This allows the mutator thread to dump its backtrace when a GC thread crashes. ruby/mmtk@40ff9ffee7
1 parent 16feb46 commit 60d9b10

File tree

4 files changed

+40
-2
lines changed

4 files changed

+40
-2
lines changed

gc/mmtk/mmtk.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ struct objspace {
3838
pthread_cond_t cond_world_started;
3939
size_t start_the_world_count;
4040

41+
struct {
42+
bool gc_thread_crashed;
43+
char crash_msg[256];
44+
} crash_context;
45+
4146
struct rb_gc_vm_context vm_context;
4247

4348
unsigned int fork_hook_vm_lock_lev;
@@ -169,6 +174,10 @@ rb_mmtk_block_for_gc(MMTk_VMMutatorThread mutator)
169174
pthread_cond_wait(&objspace->cond_world_started, &objspace->mutex);
170175
}
171176

177+
if (RB_UNLIKELY(objspace->crash_context.gc_thread_crashed)) {
178+
rb_bug("%s", objspace->crash_context.crash_msg);
179+
}
180+
172181
if (objspace->measure_gc_time) {
173182
struct timespec gc_end_time;
174183
clock_gettime(CLOCK_MONOTONIC, &gc_end_time);
@@ -424,6 +433,32 @@ rb_mmtk_special_const_p(MMTk_ObjectReference object)
424433
return RB_SPECIAL_CONST_P(obj);
425434
}
426435

436+
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2)
437+
static void
438+
rb_mmtk_gc_thread_bug(const char *msg, ...)
439+
{
440+
struct objspace *objspace = rb_gc_get_objspace();
441+
442+
objspace->crash_context.gc_thread_crashed = true;
443+
444+
va_list args;
445+
va_start(args, msg);
446+
vsnprintf(objspace->crash_context.crash_msg, sizeof(objspace->crash_context.crash_msg), msg, args);
447+
va_end(args);
448+
449+
rb_mmtk_resume_mutators();
450+
451+
sleep(5);
452+
453+
rb_bug("rb_mmtk_gc_thread_bug");
454+
}
455+
456+
static void
457+
rb_mmtk_gc_thread_panic_handler(void)
458+
{
459+
rb_mmtk_gc_thread_bug("MMTk GC thread panicked");
460+
}
461+
427462
static void
428463
rb_mmtk_mutator_thread_panic_handler(void)
429464
{
@@ -454,6 +489,7 @@ MMTk_RubyUpcalls ruby_upcalls = {
454489
rb_mmtk_update_finalizer_table,
455490
rb_mmtk_special_const_p,
456491
rb_mmtk_mutator_thread_panic_handler,
492+
rb_mmtk_gc_thread_panic_handler,
457493
};
458494

459495
// Use max 80% of the available memory by default for MMTk

gc/mmtk/mmtk.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ typedef struct MMTk_RubyUpcalls {
7979
void (*update_finalizer_table)(void);
8080
bool (*special_const_p)(MMTk_ObjectReference object);
8181
void (*mutator_thread_panic_handler)(void);
82+
void (*gc_thread_panic_handler)(void);
8283
} MMTk_RubyUpcalls;
8384

8485
typedef struct MMTk_RawVecOfObjRef {

gc/mmtk/src/abi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ pub struct RubyUpcalls {
323323
pub update_finalizer_table: extern "C" fn(),
324324
pub special_const_p: extern "C" fn(object: ObjectReference) -> bool,
325325
pub mutator_thread_panic_handler: extern "C" fn(),
326+
pub gc_thread_panic_handler: extern "C" fn(),
326327
}
327328

328329
unsafe impl Sync for RubyUpcalls {}

gc/mmtk/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,6 @@ fn handle_gc_thread_panic(panic_info: &PanicHookInfo) {
126126
eprintln!("Unknown backtrace status: {s:?}");
127127
}
128128
}
129-
130-
std::process::abort();
131129
}
132130

133131
pub(crate) fn set_panic_hook() {
@@ -140,6 +138,8 @@ pub(crate) fn set_panic_hook() {
140138
std::panic::set_hook(Box::new(move |panic_info| {
141139
if is_gc_thread(std::thread::current().id()) {
142140
handle_gc_thread_panic(panic_info);
141+
142+
(crate::binding().upcalls().gc_thread_panic_handler)();
143143
} else {
144144
old_hook(panic_info);
145145
(crate::MUTATOR_THREAD_PANIC_HANDLER

0 commit comments

Comments
 (0)