diff --git a/internal/signal.h b/internal/signal.h index 2363bf412cfbb2..904747e226a05f 100644 --- a/internal/signal.h +++ b/internal/signal.h @@ -19,6 +19,7 @@ void (*ruby_posix_signal(int, void (*)(int)))(int); RUBY_SYMBOL_EXPORT_BEGIN /* signal.c (export) */ +void rb_signal_atfork(void); RUBY_SYMBOL_EXPORT_END #endif /* INTERNAL_SIGNAL_H */ diff --git a/signal.c b/signal.c index c8120087e74e7e..9edac5a7896fb7 100644 --- a/signal.c +++ b/signal.c @@ -664,6 +664,10 @@ ruby_nativethread_signal(int signum, sighandler_t handler) #endif #endif +#if !defined(POSIX_SIGNAL) && !defined(SIG_GET) +static rb_nativethread_lock_t sig_check_lock; +#endif + static int signal_ignored(int sig) { @@ -678,9 +682,11 @@ signal_ignored(int sig) // SIG_GET: Returns the current value of the signal. func = signal(sig, SIG_GET); #else - // TODO: this is not a thread-safe way to do it. Needs lock. - sighandler_t old = signal(sig, SIG_DFL); + sighandler_t old; + rb_native_mutex_lock(&sig_check_lock); + old = signal(sig, SIG_DFL); signal(sig, old); + rb_native_mutex_unlock(&sig_check_lock); func = old; #endif if (func == SIG_IGN) return 1; @@ -1509,6 +1515,9 @@ Init_signal(void) rb_define_method(rb_eSignal, "signo", esignal_signo, 0); rb_alias(rb_eSignal, rb_intern_const("signm"), rb_intern_const("message")); rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1); +#if !defined(POSIX_SIGNAL) && !defined(SIG_GET) + rb_native_mutex_initialize(&sig_check_lock); +#endif // It should be ready to call rb_signal_exec() VM_ASSERT(GET_THREAD()->pending_interrupt_queue); @@ -1561,3 +1570,11 @@ Init_signal(void) rb_enable_interrupt(); } + +void +rb_signal_atfork(void) +{ +#if defined(HAVE_WORKING_FORK) && !defined(POSIX_SIGNAL) && !defined(SIG_GET) + rb_native_mutex_initialize(&sig_check_lock); +#endif +} diff --git a/thread.c b/thread.c index feb44197268986..8442a7e786d7ac 100644 --- a/thread.c +++ b/thread.c @@ -4933,6 +4933,7 @@ rb_thread_atfork_internal(rb_thread_t *th, void (*atfork)(rb_thread_t *, const r thread_sched_atfork(TH_SCHED(th)); ubf_list_atfork(); + rb_signal_atfork(); // OK. Only this thread accesses: ccan_list_for_each(&vm->ractor.set, r, vmlr_node) {