[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]