ruby-changes:35263
From: nagachika <ko1@a...>
Date: Tue, 2 Sep 2014 02:16:18 +0900 (JST)
Subject: [ruby-changes:35263] nagachika:r47345 (ruby_2_1): merge revision(s) r45911, r45912, r45917, r45918, r45919: [Backport #9820]
nagachika 2014-09-02 02:16:03 +0900 (Tue, 02 Sep 2014) New Revision: 47345 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=47345 Log: merge revision(s) r45911,r45912,r45917,r45918,r45919: [Backport #9820] * signal.c (rb_f_kill): directly enqueue an ignored signal to self, except for SIGSEGV and SIGBUS. [ruby-dev:48203] [Bug #9820] Modified directories: branches/ruby_2_1/ Modified files: branches/ruby_2_1/ChangeLog branches/ruby_2_1/signal.c branches/ruby_2_1/test/ruby/test_process.rb branches/ruby_2_1/test/ruby/test_signal.rb branches/ruby_2_1/thread.c branches/ruby_2_1/version.h Index: ruby_2_1/ChangeLog =================================================================== --- ruby_2_1/ChangeLog (revision 47344) +++ ruby_2_1/ChangeLog (revision 47345) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_1/ChangeLog#L1 +Tue Sep 2 02:08:12 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] + Sun Aug 31 01:13:21 2014 Koichi Sasada <ko1@a...> * gc.c: change full GC timing to keep lower memory usage. Index: ruby_2_1/thread.c =================================================================== --- ruby_2_1/thread.c (revision 47344) +++ ruby_2_1/thread.c (revision 47345) @@ -5320,13 +5320,12 @@ ruby_kill(rb_pid_t pid, int sig) https://github.com/ruby/ruby/blob/trunk/ruby_2_1/thread.c#L5320 { int err; rb_thread_t *th = GET_THREAD(); - rb_vm_t *vm = GET_VM(); /* * When target pid is self, many caller assume signal will be * delivered immediately and synchronously. */ - if ((sig != 0) && (th == vm->main_thread) && (pid == getpid())) { + { GVL_UNLOCK_BEGIN(); native_mutex_lock(&th->interrupt_lock); err = kill(pid, sig); @@ -5334,9 +5333,7 @@ ruby_kill(rb_pid_t pid, int sig) https://github.com/ruby/ruby/blob/trunk/ruby_2_1/thread.c#L5333 native_mutex_unlock(&th->interrupt_lock); GVL_UNLOCK_END(); } - else { - err = kill(pid, sig); - } - if (err < 0) + if (err < 0) { rb_sys_fail(0); + } } Index: ruby_2_1/version.h =================================================================== --- ruby_2_1/version.h (revision 47344) +++ ruby_2_1/version.h (revision 47345) @@ -1,10 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_1/version.h#L1 #define RUBY_VERSION "2.1.2" -#define RUBY_RELEASE_DATE "2014-08-31" -#define RUBY_PATCHLEVEL 216 +#define RUBY_RELEASE_DATE "2014-09-02" +#define RUBY_PATCHLEVEL 217 #define RUBY_RELEASE_YEAR 2014 -#define RUBY_RELEASE_MONTH 8 -#define RUBY_RELEASE_DAY 31 +#define RUBY_RELEASE_MONTH 9 +#define RUBY_RELEASE_DAY 2 #include "ruby/version.h" Index: ruby_2_1/test/ruby/test_signal.rb =================================================================== --- ruby_2_1/test/ruby/test_signal.rb (revision 47344) +++ ruby_2_1/test/ruby/test_signal.rb (revision 47345) @@ -268,4 +268,15 @@ EOS https://github.com/ruby/ruby/blob/trunk/ruby_2_1/test/ruby/test_signal.rb#L268 } } 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: ruby_2_1/test/ruby/test_process.rb =================================================================== --- ruby_2_1/test/ruby/test_process.rb (revision 47344) +++ ruby_2_1/test/ruby/test_process.rb (revision 47345) @@ -1193,6 +1193,23 @@ class TestProcess < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/ruby_2_1/test/ruby/test_process.rb#L1193 def test_status_kill return unless Process.respond_to?(:kill) + return unless Signal.list.include?("KILL") + + # assume the system supports signal if SIGQUIT is available + expected = Signal.list.include?("QUIT") ? [false, true, false, nil] : [true, false, false, true] + + with_tmpchdir do + write_file("foo", "Process.kill(:KILL, $$); exit(42)") + system(RUBY, "foo") + s = $? + assert_equal(expected, + [s.exited?, s.signaled?, s.stopped?, s.success?], + "[s.exited?, s.signaled?, s.stopped?, s.success?]") + end + end + + def test_status_quit + return unless Process.respond_to?(:kill) return unless Signal.list.include?("QUIT") with_tmpchdir do @@ -1206,16 +1223,14 @@ class TestProcess < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/ruby_2_1/test/ruby/test_process.rb#L1223 end t = Time.now s = $? - assert_equal([false, true, false], - [s.exited?, s.signaled?, s.stopped?], - "[s.exited?, s.signaled?, s.stopped?]") + assert_equal([false, true, false, nil], + [s.exited?, s.signaled?, s.stopped?, s.success?], + "[s.exited?, s.signaled?, s.stopped?, s.success?]") assert_send( [["#<Process::Status: pid #{ s.pid } SIGQUIT (signal #{ s.termsig })>", "#<Process::Status: pid #{ s.pid } SIGQUIT (signal #{ s.termsig }) (core dumped)>"], :include?, s.inspect]) - assert_equal(false, s.exited?) - assert_equal(nil, s.success?) EnvUtil.diagnostic_reports("QUIT", RUBY, pid, t) end end Index: ruby_2_1/signal.c =================================================================== --- ruby_2_1/signal.c (revision 47344) +++ ruby_2_1/signal.c (revision 47345) @@ -343,6 +343,9 @@ ruby_default_signal(int sig) https://github.com/ruby/ruby/blob/trunk/ruby_2_1/signal.c#L343 raise(sig); } +static int signal_ignored(int sig); +static void signal_enque(int sig); + /* * call-seq: * Process.kill(signal, pid, ...) -> fixnum @@ -429,6 +432,8 @@ rb_f_kill(int argc, VALUE *argv) https://github.com/ruby/ruby/blob/trunk/ruby_2_1/signal.c#L432 break; } + if (argc <= 1) return INT2FIX(0); + if (sig < 0) { sig = -sig; for (i=1; i<argc; i++) { @@ -437,8 +442,42 @@ rb_f_kill(int argc, VALUE *argv) https://github.com/ruby/ruby/blob/trunk/ruby_2_1/signal.c#L442 } } 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 +#ifdef SIGKILL + case SIGKILL: +#endif +#ifdef SIGSTOP + case SIGSTOP: +#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()); @@ -570,11 +609,32 @@ ruby_nativethread_signal(int signum, sig https://github.com/ruby/ruby/blob/trunk/ruby_2_1/signal.c#L609 #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); Property changes on: ruby_2_1 ___________________________________________________________________ Modified: svn:mergeinfo Merged /trunk:r45911-45912,45917-45919 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/