Skip to content

Commit 75961b2

Browse files
committed
handle some cases of null Task in segv handling (#42836)
Also ensure we do not use round-robin sampling when printing a critical error, only for profiling. (cherry picked from commit ad607a2)
1 parent b825b2d commit 75961b2

File tree

7 files changed

+76
-75
lines changed

7 files changed

+76
-75
lines changed

src/gf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1826,7 +1826,7 @@ static void JL_NORETURN jl_method_error_bare(jl_function_t *f, jl_value_t *args,
18261826
jl_static_show((JL_STREAM*)STDERR_FILENO,args); jl_printf((JL_STREAM*)STDERR_FILENO,"\n");
18271827
jl_ptls_t ptls = jl_current_task->ptls;
18281828
ptls->bt_size = rec_backtrace(ptls->bt_data, JL_MAX_BT_SIZE, 0);
1829-
jl_critical_error(0, NULL);
1829+
jl_critical_error(0, NULL, jl_current_task);
18301830
abort();
18311831
}
18321832
// not reached

src/julia_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,7 @@ size_t rec_backtrace_ctx(jl_bt_element_t *bt_data, size_t maxsize, bt_context_t
981981
size_t rec_backtrace_ctx_dwarf(jl_bt_element_t *bt_data, size_t maxsize, bt_context_t *ctx, jl_gcframe_t *pgcstack) JL_NOTSAFEPOINT;
982982
#endif
983983
JL_DLLEXPORT jl_value_t *jl_get_backtrace(void);
984-
void jl_critical_error(int sig, bt_context_t *context);
984+
void jl_critical_error(int sig, bt_context_t *context, jl_task_t *ct);
985985
JL_DLLEXPORT void jl_raise_debugger(void);
986986
int jl_getFunctionInfo(jl_frame_t **frames, uintptr_t pointer, int skipC, int noInline) JL_NOTSAFEPOINT;
987987
JL_DLLEXPORT void jl_gdblookup(void* ip) JL_NOTSAFEPOINT;

src/signal-handling.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -231,19 +231,20 @@ void jl_show_sigill(void *_ctx)
231231
}
232232

233233
// what to do on a critical error on a thread
234-
void jl_critical_error(int sig, bt_context_t *context)
234+
void jl_critical_error(int sig, bt_context_t *context, jl_task_t *ct)
235235
{
236236

237-
jl_task_t *ct = jl_current_task;
238-
jl_bt_element_t *bt_data = ct->ptls->bt_data;
239-
size_t *bt_size = &ct->ptls->bt_size;
240-
size_t i, n = *bt_size;
237+
jl_bt_element_t *bt_data = ct ? ct->ptls->bt_data : NULL;
238+
size_t *bt_size = ct ? &ct->ptls->bt_size : NULL;
239+
size_t i, n = ct ? *bt_size : 0;
241240
if (sig) {
242241
// kill this task, so that we cannot get back to it accidentally (via an untimely ^C or jlbacktrace in jl_exit)
243242
jl_set_safe_restore(NULL);
244-
ct->gcstack = NULL;
245-
ct->eh = NULL;
246-
ct->excstack = NULL;
243+
if (ct) {
244+
ct->gcstack = NULL;
245+
ct->eh = NULL;
246+
ct->excstack = NULL;
247+
}
247248
#ifndef _OS_WINDOWS_
248249
sigset_t sset;
249250
sigemptyset(&sset);
@@ -267,7 +268,7 @@ void jl_critical_error(int sig, bt_context_t *context)
267268
jl_safe_printf("\nsignal (%d): %s\n", sig, strsignal(sig));
268269
}
269270
jl_safe_printf("in expression starting at %s:%d\n", jl_filename, jl_lineno);
270-
if (context) {
271+
if (context && ct) {
271272
// Must avoid extended backtrace frames here unless we're sure bt_data
272273
// is properly rooted.
273274
*bt_size = n = rec_backtrace_ctx(bt_data, JL_MAX_BT_SIZE, context, NULL);

src/signals-mach.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ static void jl_try_deliver_sigint(void)
402402
static void JL_NORETURN jl_exit_thread0_cb(int exitstate)
403403
{
404404
CFI_NORETURN
405-
jl_critical_error(exitstate - 128, NULL);
405+
jl_critical_error(exitstate - 128, NULL, jl_current_task);
406406
jl_exit(exitstate);
407407
}
408408

src/signals-unix.c

Lines changed: 57 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ static void sigdie_handler(int sig, siginfo_t *info, void *context)
227227
uv_tty_reset_mode();
228228
if (sig == SIGILL)
229229
jl_show_sigill(context);
230-
jl_critical_error(sig, jl_to_bt_context(context));
230+
jl_critical_error(sig, jl_to_bt_context(context), jl_get_current_task());
231231
if (sig != SIGSEGV &&
232232
sig != SIGBUS &&
233233
sig != SIGILL) {
@@ -406,7 +406,7 @@ CFI_NORETURN
406406
// (unavoidable due to its async nature).
407407
// Try harder to exit each time if we get multiple exit requests.
408408
if (thread0_exit_count <= 1) {
409-
jl_critical_error(thread0_exit_state - 128, NULL);
409+
jl_critical_error(thread0_exit_state - 128, NULL, jl_current_task);
410410
jl_exit(thread0_exit_state);
411411
}
412412
else if (thread0_exit_count == 2) {
@@ -743,68 +743,68 @@ static void *signal_listener(void *arg)
743743
unw_context_t *signal_context;
744744
// sample each thread, round-robin style in reverse order
745745
// (so that thread zero gets notified last)
746-
if (critical || profile)
746+
if (critical || profile) {
747747
jl_lock_profile();
748-
for (int i = jl_n_threads; i-- > 0; ) {
749-
// notify thread to stop
750-
jl_thread_suspend_and_get_state(i, &signal_context);
751-
752-
// do backtrace on thread contexts for critical signals
753-
// this part must be signal-handler safe
754-
if (critical) {
755-
bt_size += rec_backtrace_ctx(bt_data + bt_size,
756-
JL_MAX_BT_SIZE / jl_n_threads - 1,
757-
signal_context, NULL);
758-
bt_data[bt_size++].uintptr = 0;
759-
}
760-
761-
// do backtrace for profiler
762-
if (profile && running) {
763-
if (jl_profile_is_buffer_full()) {
764-
// Buffer full: Delete the timer
765-
jl_profile_stop_timer();
748+
for (int i = jl_n_threads; i-- > 0; ) {
749+
// notify thread to stop
750+
jl_thread_suspend_and_get_state(i, &signal_context);
751+
752+
// do backtrace on thread contexts for critical signals
753+
// this part must be signal-handler safe
754+
if (critical) {
755+
bt_size += rec_backtrace_ctx(bt_data + bt_size,
756+
JL_MAX_BT_SIZE / jl_n_threads - 1,
757+
signal_context, NULL);
758+
bt_data[bt_size++].uintptr = 0;
766759
}
767-
else {
768-
// unwinding can fail, so keep track of the current state
769-
// and restore from the SEGV handler if anything happens.
770-
jl_jmp_buf *old_buf = jl_get_safe_restore();
771-
jl_jmp_buf buf;
772-
773-
jl_set_safe_restore(&buf);
774-
if (jl_setjmp(buf, 0)) {
775-
jl_safe_printf("WARNING: profiler attempt to access an invalid memory location\n");
776-
} else {
777-
// Get backtrace data
778-
bt_size_cur += rec_backtrace_ctx((jl_bt_element_t*)bt_data_prof + bt_size_cur,
779-
bt_size_max - bt_size_cur - 1, signal_context, NULL);
780-
}
781-
jl_set_safe_restore(old_buf);
782-
783-
jl_ptls_t ptls = jl_all_tls_states[i];
784-
785-
// store threadid but add 1 as 0 is preserved to indicate end of block
786-
bt_data_prof[bt_size_cur++].uintptr = ptls->tid + 1;
787-
788-
// store task id
789-
bt_data_prof[bt_size_cur++].jlvalue = (jl_value_t*)ptls->current_task;
790760

791-
// store cpu cycle clock
792-
bt_data_prof[bt_size_cur++].uintptr = cycleclock();
793-
794-
// store whether thread is sleeping but add 1 as 0 is preserved to indicate end of block
795-
bt_data_prof[bt_size_cur++].uintptr = ptls->sleep_check_state + 1;
761+
// do backtrace for profiler
762+
if (profile && running) {
763+
if (jl_profile_is_buffer_full()) {
764+
// Buffer full: Delete the timer
765+
jl_profile_stop_timer();
766+
}
767+
else {
768+
// unwinding can fail, so keep track of the current state
769+
// and restore from the SEGV handler if anything happens.
770+
jl_jmp_buf *old_buf = jl_get_safe_restore();
771+
jl_jmp_buf buf;
772+
773+
jl_set_safe_restore(&buf);
774+
if (jl_setjmp(buf, 0)) {
775+
jl_safe_printf("WARNING: profiler attempt to access an invalid memory location\n");
776+
} else {
777+
// Get backtrace data
778+
bt_size_cur += rec_backtrace_ctx((jl_bt_element_t*)bt_data_prof + bt_size_cur,
779+
bt_size_max - bt_size_cur - 1, signal_context, NULL);
780+
}
781+
jl_set_safe_restore(old_buf);
782+
783+
jl_ptls_t ptls = jl_all_tls_states[i];
784+
785+
// store threadid but add 1 as 0 is preserved to indicate end of block
786+
bt_data_prof[bt_size_cur++].uintptr = ptls->tid + 1;
787+
788+
// store task id
789+
bt_data_prof[bt_size_cur++].jlvalue = (jl_value_t*)ptls->current_task;
790+
791+
// store cpu cycle clock
792+
bt_data_prof[bt_size_cur++].uintptr = cycleclock();
793+
794+
// store whether thread is sleeping but add 1 as 0 is preserved to indicate end of block
795+
bt_data_prof[bt_size_cur++].uintptr = ptls->sleep_check_state + 1;
796+
797+
// Mark the end of this block with two 0's
798+
bt_data_prof[bt_size_cur++].uintptr = 0;
799+
bt_data_prof[bt_size_cur++].uintptr = 0;
800+
}
796801

797-
// Mark the end of this block with two 0's
798-
bt_data_prof[bt_size_cur++].uintptr = 0;
799-
bt_data_prof[bt_size_cur++].uintptr = 0;
802+
// notify thread to resume
803+
jl_thread_resume(i, sig);
800804
}
801805
}
802-
803-
// notify thread to resume
804-
jl_thread_resume(i, sig);
805-
}
806-
if (critical || profile)
807806
jl_unlock_profile();
807+
}
808808
#ifndef HAVE_MACH
809809
if (profile && running) {
810810
#if defined(HAVE_TIMER)

src/signals-win.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ static void jl_try_throw_sigint(void)
5959

6060
void __cdecl crt_sig_handler(int sig, int num)
6161
{
62-
jl_task_t *ct = jl_current_task;
6362
CONTEXT Context;
6463
switch (sig) {
6564
case SIGFPE:
@@ -92,7 +91,7 @@ void __cdecl crt_sig_handler(int sig, int num)
9291
RtlCaptureContext(&Context);
9392
if (sig == SIGILL)
9493
jl_show_sigill(&Context);
95-
jl_critical_error(sig, &Context);
94+
jl_critical_error(sig, &Context, jl_get_current_task());
9695
raise(sig);
9796
}
9897
}
@@ -226,7 +225,8 @@ static BOOL WINAPI sigint_handler(DWORD wsig) //This needs winapi types to guara
226225

227226
LONG WINAPI jl_exception_handler(struct _EXCEPTION_POINTERS *ExceptionInfo)
228227
{
229-
jl_ptls_t ptls = jl_current_task->ptls;
228+
jl_task_t *ct = jl_current_task;
229+
jl_ptls_t ptls = ct->ptls;
230230
if (ExceptionInfo->ExceptionRecord->ExceptionFlags == 0) {
231231
switch (ExceptionInfo->ExceptionRecord->ExceptionCode) {
232232
case EXCEPTION_INT_DIVIDE_BY_ZERO:
@@ -313,7 +313,7 @@ LONG WINAPI jl_exception_handler(struct _EXCEPTION_POINTERS *ExceptionInfo)
313313
jl_safe_printf(" at 0x%Ix -- ", (size_t)ExceptionInfo->ExceptionRecord->ExceptionAddress);
314314
jl_print_native_codeloc((uintptr_t)ExceptionInfo->ExceptionRecord->ExceptionAddress);
315315

316-
jl_critical_error(0, ExceptionInfo->ContextRecord);
316+
jl_critical_error(0, ExceptionInfo->ContextRecord, ct);
317317
static int recursion = 0;
318318
if (recursion++)
319319
exit(1);

src/threading.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ JL_DLLEXPORT void jl_set_safe_restore(jl_jmp_buf *sr)
176176
JL_CONST_FUNC jl_gcframe_t **jl_get_pgcstack(void) JL_NOTSAFEPOINT
177177
{
178178
SAVE_ERRNO;
179-
jl_gcframe_t **pgcstack = (jl_ptls_t)TlsGetValue(jl_pgcstack_key);
179+
jl_gcframe_t **pgcstack = (jl_gcframe_t**)TlsGetValue(jl_pgcstack_key);
180180
LOAD_ERRNO;
181181
return pgcstack;
182182
}
@@ -226,7 +226,7 @@ static jl_gcframe_t ***jl_pgcstack_addr_fallback(void) JL_NOTSAFEPOINT
226226
}
227227
void jl_set_pgcstack(jl_gcframe_t **pgcstack) JL_NOTSAFEPOINT
228228
{
229-
*jl_pgcstack_key() = pgcstack;
229+
*(jl_gcframe_t**)jl_pgcstack_key() = pgcstack;
230230
}
231231
# if JL_USE_IFUNC
232232
JL_DLLEXPORT __attribute__((weak))

0 commit comments

Comments
 (0)