mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 05:29:10 +02:00
Fix race condition in signal handler query (#13712)
* Fix race condition in signal handler query * Initialize signal lock dynamically and reset after fork * Fix signal handler mutex initialization conditions
This commit is contained in:
parent
31c1f3665a
commit
eab4a0bc8d
3 changed files with 21 additions and 2 deletions
|
@ -19,6 +19,7 @@ void (*ruby_posix_signal(int, void (*)(int)))(int);
|
||||||
|
|
||||||
RUBY_SYMBOL_EXPORT_BEGIN
|
RUBY_SYMBOL_EXPORT_BEGIN
|
||||||
/* signal.c (export) */
|
/* signal.c (export) */
|
||||||
|
void rb_signal_atfork(void);
|
||||||
RUBY_SYMBOL_EXPORT_END
|
RUBY_SYMBOL_EXPORT_END
|
||||||
|
|
||||||
#endif /* INTERNAL_SIGNAL_H */
|
#endif /* INTERNAL_SIGNAL_H */
|
||||||
|
|
21
signal.c
21
signal.c
|
@ -664,6 +664,10 @@ ruby_nativethread_signal(int signum, sighandler_t handler)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(POSIX_SIGNAL) && !defined(SIG_GET)
|
||||||
|
static rb_nativethread_lock_t sig_check_lock;
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
signal_ignored(int sig)
|
signal_ignored(int sig)
|
||||||
{
|
{
|
||||||
|
@ -678,9 +682,11 @@ signal_ignored(int sig)
|
||||||
// SIG_GET: Returns the current value of the signal.
|
// SIG_GET: Returns the current value of the signal.
|
||||||
func = signal(sig, SIG_GET);
|
func = signal(sig, SIG_GET);
|
||||||
#else
|
#else
|
||||||
// TODO: this is not a thread-safe way to do it. Needs lock.
|
sighandler_t old;
|
||||||
sighandler_t old = signal(sig, SIG_DFL);
|
rb_native_mutex_lock(&sig_check_lock);
|
||||||
|
old = signal(sig, SIG_DFL);
|
||||||
signal(sig, old);
|
signal(sig, old);
|
||||||
|
rb_native_mutex_unlock(&sig_check_lock);
|
||||||
func = old;
|
func = old;
|
||||||
#endif
|
#endif
|
||||||
if (func == SIG_IGN) return 1;
|
if (func == SIG_IGN) return 1;
|
||||||
|
@ -1509,6 +1515,9 @@ Init_signal(void)
|
||||||
rb_define_method(rb_eSignal, "signo", esignal_signo, 0);
|
rb_define_method(rb_eSignal, "signo", esignal_signo, 0);
|
||||||
rb_alias(rb_eSignal, rb_intern_const("signm"), rb_intern_const("message"));
|
rb_alias(rb_eSignal, rb_intern_const("signm"), rb_intern_const("message"));
|
||||||
rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);
|
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()
|
// It should be ready to call rb_signal_exec()
|
||||||
VM_ASSERT(GET_THREAD()->pending_interrupt_queue);
|
VM_ASSERT(GET_THREAD()->pending_interrupt_queue);
|
||||||
|
@ -1561,3 +1570,11 @@ Init_signal(void)
|
||||||
|
|
||||||
rb_enable_interrupt();
|
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
|
||||||
|
}
|
||||||
|
|
1
thread.c
1
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));
|
thread_sched_atfork(TH_SCHED(th));
|
||||||
ubf_list_atfork();
|
ubf_list_atfork();
|
||||||
|
rb_signal_atfork();
|
||||||
|
|
||||||
// OK. Only this thread accesses:
|
// OK. Only this thread accesses:
|
||||||
ccan_list_for_each(&vm->ractor.set, r, vmlr_node) {
|
ccan_list_for_each(&vm->ractor.set, r, vmlr_node) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue