ruby-changes:33830
From: nobu <ko1@a...>
Date: Sun, 11 May 2014 01:10:46 +0900 (JST)
Subject: [ruby-changes:33830] nobu:r45911 (trunk): signal.c: directly enqueue
nobu 2014-05-11 01:10:32 +0900 (Sun, 11 May 2014) New Revision: 45911 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=45911 Log: signal.c: directly enqueue * signal.c (rb_f_kill): directly enqueue an ignored signal to self, except for SIGSEGV and SIGBUS. [ruby-dev:48203] [Bug #9820] Modified files: trunk/ChangeLog trunk/signal.c trunk/test/ruby/test_signal.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 45910) +++ ChangeLog (revision 45911) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Sun May 11 01:10:31 2014 Nobuyoshi Nakada <nobu@r...> + + * signal.c (rb_f_kill): directly enqueue an ignored signal to self, + except for SIGSEGV and SIGBUS. [ruby-dev:48203] [Bug #9820] + Sat May 10 22:37:56 2014 Nobuyoshi Nakada <nobu@r...> * dir.c (push_glob): match in UTF-8 on Mac OS X. Index: test/ruby/test_signal.rb =================================================================== --- test/ruby/test_signal.rb (revision 45910) +++ test/ruby/test_signal.rb (revision 45911) @@ -276,4 +276,15 @@ EOS https://github.com/ruby/ruby/blob/trunk/test/ruby/test_signal.rb#L276 } } end if Process.respond_to?(:kill) and Signal.list.key?('HUP') + + def test_ignored_interrupt + bug9820 = '[ruby-dev:48203] [Bug #9820]' + assert_separately(['-', bug9820], <<-'end;') # begin + bug = ARGV.shift + trap(:INT, "IGNORE") + assert_nothing_raised(SignalException, bug) do + Process.kill(:INT, $$) + end + end; + end if Process.respond_to?(:kill) end Index: signal.c =================================================================== --- signal.c (revision 45910) +++ signal.c (revision 45911) @@ -350,6 +350,9 @@ ruby_default_signal(int sig) https://github.com/ruby/ruby/blob/trunk/signal.c#L350 raise(sig); } +static int signal_ignored(int sig); +static void signal_enque(int sig); + /* * call-seq: * Process.kill(signal, pid, ...) -> fixnum @@ -436,6 +439,8 @@ rb_f_kill(int argc, VALUE *argv) https://github.com/ruby/ruby/blob/trunk/signal.c#L439 break; } + if (argc <= 1) return INT2FIX(0); + if (sig < 0) { sig = -sig; for (i=1; i<argc; i++) { @@ -444,8 +449,36 @@ rb_f_kill(int argc, VALUE *argv) https://github.com/ruby/ruby/blob/trunk/signal.c#L449 } } else { + const rb_pid_t self = (GET_THREAD() == GET_VM()->main_thread) ? getpid() : -1; + int wakeup = 0; + for (i=1; i<argc; i++) { - ruby_kill(NUM2PIDT(argv[i]), sig); + rb_pid_t pid = NUM2PIDT(argv[i]); + + if ((sig != 0) && (self != -1) && (pid == self)) { + /* + * When target pid is self, many caller assume signal will be + * delivered immediately and synchronously. + */ + switch (sig) { + case SIGSEGV: +#ifdef SIGBUS + case SIGBUS: +#endif + ruby_kill(pid, sig); + break; + default: + if (signal_ignored(sig)) break; + signal_enque(sig); + wakeup = 1; + } + } + else if (kill(pid, sig) < 0) { + rb_sys_fail(0); + } + } + if (wakeup) { + rb_threadptr_check_signal(GET_VM()->main_thread); } } rb_thread_execute_interrupts(rb_thread_current()); @@ -578,11 +611,32 @@ ruby_nativethread_signal(int signum, sig https://github.com/ruby/ruby/blob/trunk/signal.c#L611 #endif #endif -static RETSIGTYPE -sighandler(int sig) +static int +signal_ignored(int sig) +{ +#ifdef POSIX_SIGNAL + struct sigaction old; + (void)VALGRIND_MAKE_MEM_DEFINED(&old, sizeof(old)); + if (sigaction(sig, NULL, &old) < 0) return FALSE; + return old.sa_handler == SIG_IGN; +#else + sighandler_t old = signal(sig, SIG_DFL); + signal(sig, old); + return old == SIG_IGN; +#endif +} + +static void +signal_enque(int sig) { ATOMIC_INC(signal_buff.cnt[sig]); ATOMIC_INC(signal_buff.size); +} + +static RETSIGTYPE +sighandler(int sig) +{ + signal_enque(sig); rb_thread_wakeup_timer_thread(); #if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL) ruby_signal(sig, sighandler); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/