dumping ground for random patches and texts
 help / color / mirror / Atom feed
From: Eric Wong <e@80x24.org>
To: spew@80x24.org
Subject: [PATCH] ensure Process.kill(:STOP, $$) is resumable
Date: Fri, 17 Jul 2015 09:22:37 +0000	[thread overview]
Message-ID: <1437124957-4107-1-git-send-email-e@80x24.org> (raw)

Self-inflicted signals are delivered immediately.  This is fine
for most signals which are catchable, but SIGSTOP and SIGKILL
are special and cannot be caught by a userspace process.

SIGKILL is easy, the process will die immediately and we won't
care for it.  However, SIGSTOP is tricky because we cannot know
when it is delivered.  Try to improve the situation by allowing
the OS to reschedule our thread by calling native_thread_yield().

* thread.c (ruby_kill): do not sleep forever on SIGSTOP
---
 test/ruby/test_process.rb | 23 +++++++++++++++++++++++
 thread.c                  | 16 +++++++++++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb
index 00bbf9e..fa84a9f 100644
--- a/test/ruby/test_process.rb
+++ b/test/ruby/test_process.rb
@@ -1341,6 +1341,29 @@ class TestProcess < Test::Unit::TestCase
     end
   end
 
+  def test_status_stop_self_resumable
+    skip "kill not supported" unless Process.respond_to?(:kill)
+    skip "fork not supported" unless Process.respond_to?(:fork)
+    skip "SIGSTOP not supported" unless Signal.list.include?("STOP")
+    skip "WUNTRACED not defined" unless Process.const_defined?(:WUNTRACED)
+    pid = nil
+    Timeout.timeout(30) do
+      pid = fork do
+        Process.kill(:STOP, $$)
+        exit(42)
+      end
+      _, s = Process.waitpid2(pid, Process::WUNTRACED)
+      assert_predicate s, :stopped?
+      Process.kill(:CONT, pid)
+      _, s = Process.waitpid2(pid)
+      assert_predicate s, :exited?
+      assert_equal 42, s.exitstatus
+    end
+  rescue Timeout::Error
+    Process.kill(:KILL, pid) if pid
+    raise
+  end
+
   def test_wait_without_arg
     with_tmpchdir do
       write_file("foo", "sleep 0.1")
diff --git a/thread.c b/thread.c
index 1d550ef..f0da75d 100644
--- a/thread.c
+++ b/thread.c
@@ -5262,6 +5262,11 @@ ruby_kill(rb_pid_t pid, int sig)
 {
     int err;
     rb_thread_t *th = GET_THREAD();
+#ifdef SIGSTOP
+    int sigstop = sig == SIGSTOP;
+#else
+    int sigstop = 0;
+#endif
 
     /*
      * When target pid is self, many caller assume signal will be
@@ -5271,7 +5276,16 @@ ruby_kill(rb_pid_t pid, int sig)
 	GVL_UNLOCK_BEGIN();
 	native_mutex_lock(&th->interrupt_lock);
 	err = kill(pid, sig);
-	native_cond_wait(&th->interrupt_cond, &th->interrupt_lock);
+	if (sigstop) {
+	    /*
+	     * best effort to try to receive SIGSTOP ASAP,
+	     * maybe we need to yield several more times.
+	     */
+	    native_thread_yield();
+	}
+	else { /* sig is SIGKILL, SIGSEGV, or SIGBUS: wait to die */
+	    native_cond_wait(&th->interrupt_cond, &th->interrupt_lock);
+	}
 	native_mutex_unlock(&th->interrupt_lock);
 	GVL_UNLOCK_END();
     }
-- 
EW


                 reply	other threads:[~2015-07-17  9:22 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1437124957-4107-1-git-send-email-e@80x24.org \
    --to=e@80x24.org \
    --cc=spew@80x24.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).