@@ -446,6 +446,113 @@ static void stack_overflow_warning(void)
446446 jl_safe_printf ("Warning: detected a stack overflow; program state may be corrupted, so further execution might be unreliable.\n" );
447447}
448448
449+ // Async-signal-safe replacement for libc strsignal(). We call this from fatal-signal
450+ // handlers, and glibc's strsignal() is not async-signal-safe: it routes through gettext
451+ // (to localize the description), which calls malloc(). If the interrupted thread already
452+ // held the malloc arena lock, that reentrant malloc() self-deadlocks. A fixed table of
453+ // string literals avoids gettext/malloc entirely and is portable across libc flavors
454+ // (musl/BSD/macOS lack glibc's sigdescr_np/sigabbrev_np). Cases are #ifdef-guarded so this
455+ // compiles wherever a given signal is (or is not) defined.
456+ static const char * jl_strsignal (int sig ) JL_NOTSAFEPOINT
457+ {
458+ switch (sig ) {
459+ #ifdef SIGHUP
460+ case SIGHUP : return "Hangup" ;
461+ #endif
462+ #ifdef SIGINT
463+ case SIGINT : return "Interrupt" ;
464+ #endif
465+ #ifdef SIGQUIT
466+ case SIGQUIT : return "Quit" ;
467+ #endif
468+ #ifdef SIGILL
469+ case SIGILL : return "Illegal instruction" ;
470+ #endif
471+ #ifdef SIGTRAP
472+ case SIGTRAP : return "Trace/breakpoint trap" ;
473+ #endif
474+ #ifdef SIGABRT
475+ case SIGABRT : return "Aborted" ;
476+ #endif
477+ #if defined(SIGABRT_COMPAT ) && (!defined(SIGABRT ) || SIGABRT_COMPAT != SIGABRT )
478+ case SIGABRT_COMPAT : return "Aborted" ;
479+ #endif
480+ #ifdef SIGBUS
481+ case SIGBUS : return "Bus error" ;
482+ #endif
483+ #ifdef SIGFPE
484+ case SIGFPE : return "Floating point exception" ;
485+ #endif
486+ #ifdef SIGKILL
487+ case SIGKILL : return "Killed" ;
488+ #endif
489+ #ifdef SIGUSR1
490+ case SIGUSR1 : return "User defined signal 1" ;
491+ #endif
492+ #ifdef SIGSEGV
493+ case SIGSEGV : return "Segmentation fault" ;
494+ #endif
495+ #ifdef SIGUSR2
496+ case SIGUSR2 : return "User defined signal 2" ;
497+ #endif
498+ #ifdef SIGPIPE
499+ case SIGPIPE : return "Broken pipe" ;
500+ #endif
501+ #ifdef SIGALRM
502+ case SIGALRM : return "Alarm clock" ;
503+ #endif
504+ #ifdef SIGTERM
505+ case SIGTERM : return "Terminated" ;
506+ #endif
507+ #ifdef SIGBREAK
508+ case SIGBREAK : return "Break" ;
509+ #endif
510+ #ifdef SIGSTKFLT
511+ case SIGSTKFLT : return "Stack fault" ;
512+ #endif
513+ #ifdef SIGCHLD
514+ case SIGCHLD : return "Child exited" ;
515+ #endif
516+ #ifdef SIGCONT
517+ case SIGCONT : return "Continued" ;
518+ #endif
519+ #ifdef SIGSTOP
520+ case SIGSTOP : return "Stopped (signal)" ;
521+ #endif
522+ #ifdef SIGTSTP
523+ case SIGTSTP : return "Stopped" ;
524+ #endif
525+ #ifdef SIGTTIN
526+ case SIGTTIN : return "Stopped (tty input)" ;
527+ #endif
528+ #ifdef SIGTTOU
529+ case SIGTTOU : return "Stopped (tty output)" ;
530+ #endif
531+ #ifdef SIGURG
532+ case SIGURG : return "Urgent I/O condition" ;
533+ #endif
534+ #ifdef SIGXCPU
535+ case SIGXCPU : return "CPU time limit exceeded" ;
536+ #endif
537+ #ifdef SIGXFSZ
538+ case SIGXFSZ : return "File size limit exceeded" ;
539+ #endif
540+ #ifdef SIGVTALRM
541+ case SIGVTALRM : return "Virtual timer expired" ;
542+ #endif
543+ #ifdef SIGPROF
544+ case SIGPROF : return "Profiling timer expired" ;
545+ #endif
546+ #ifdef SIGWINCH
547+ case SIGWINCH : return "Window changed" ;
548+ #endif
549+ #ifdef SIGSYS
550+ case SIGSYS : return "Bad system call" ;
551+ #endif
552+ default : return "Unknown signal" ;
553+ }
554+ }
555+
449556#if defined(_WIN32 )
450557#include "signals-win.c"
451558#else
@@ -636,9 +743,9 @@ void jl_fprint_critical_error(ios_t *s, int sig, int si_code, bt_context_t *cont
636743 pthread_sigmask (SIG_UNBLOCK , & sset , NULL );
637744#endif
638745 if (si_code )
639- jl_safe_fprintf (s , "\n[%d] signal %d (%d): %s\n" , getpid (), sig , si_code , strsignal (sig ));
746+ jl_safe_fprintf (s , "\n[%d] signal %d (%d): %s\n" , getpid (), sig , si_code , jl_strsignal (sig ));
640747 else
641- jl_safe_fprintf (s , "\n[%d] signal %d: %s\n" , getpid (), sig , strsignal (sig ));
748+ jl_safe_fprintf (s , "\n[%d] signal %d: %s\n" , getpid (), sig , jl_strsignal (sig ));
642749 if (sig == SIGQUIT ) {
643750 jl_print_task_backtraces (0 );
644751 }
0 commit comments