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

ruby-changes:64563

From: Nobuyoshi <ko1@a...>
Date: Thu, 24 Dec 2020 22:59:56 +0900 (JST)
Subject: [ruby-changes:64563] bdbbfd1fa5 (master): Store errno in struct rb_process_status

https://git.ruby-lang.org/ruby.git/commit/?id=bdbbfd1fa5

From bdbbfd1fa53baac4d12530a6791140e35a9df46b Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Thu, 24 Dec 2020 16:44:38 +0900
Subject: Store errno in struct rb_process_status

To propagate errno in the fiber thread scheduler hook.
Returns nil when no terminated process.

diff --git a/process.c b/process.c
index 8fd9add..14f3bb0 100644
--- a/process.c
+++ b/process.c
@@ -572,6 +572,7 @@ static VALUE rb_cProcessStatus; https://github.com/ruby/ruby/blob/trunk/process.c#L572
 struct rb_process_status {
     rb_pid_t pid;
     int status;
+    int error;
 };
 
 static const rb_data_type_t rb_process_status_type = {
@@ -619,13 +620,14 @@ proc_s_last_status(VALUE mod) https://github.com/ruby/ruby/blob/trunk/process.c#L620
 }
 
 VALUE
-rb_process_status_new(rb_pid_t pid, int status)
+rb_process_status_new(rb_pid_t pid, int status, int error)
 {
     VALUE last_status = rb_process_status_allocate(rb_cProcessStatus);
 
     struct rb_process_status *data = RTYPEDDATA_DATA(last_status);
     data->pid = pid;
     data->status = status;
+    data->error = error;
 
     rb_obj_freeze(last_status);
     return last_status;
@@ -657,7 +659,7 @@ process_status_load(VALUE real_obj, VALUE load_obj) https://github.com/ruby/ruby/blob/trunk/process.c#L659
 void
 rb_last_status_set(int status, rb_pid_t pid)
 {
-    GET_THREAD()->last_status = rb_process_status_new(pid, status);
+    GET_THREAD()->last_status = rb_process_status_new(pid, status, 0);
 }
 
 void
@@ -1164,6 +1166,7 @@ waitpid_state_init(struct waitpid_state *w, rb_pid_t pid, int options) https://github.com/ruby/ruby/blob/trunk/process.c#L1166
     w->pid = pid;
     w->options = options;
     w->errnum = 0;
+    w->status = 0;
 }
 
 static const rb_hrtime_t *
@@ -1349,20 +1352,17 @@ rb_process_status_wait(rb_pid_t pid, int flags) https://github.com/ruby/ruby/blob/trunk/process.c#L1352
         waitpid_no_SIGCHLD(w);
     }
 
-    VALUE status = Qnil;
-    if (w->ret == -1) {
-        errno = w->errnum;
-    }
-    else if (w->ret > 0 && ruby_nocldwait) {
-        errno = ECHILD;
-    }
-    else {
-        status = rb_process_status_new(w->ret, w->status);
-    }
-
+    rb_pid_t ret = w->ret;
+    int s = w->status, e = w->errnum;
     COROUTINE_STACK_FREE(w);
 
-    return status;
+    if (ret == 0) return Qnil;
+    if (ret > 0 && ruby_nocldwait) {
+        ret = -1;
+        e = ECHILD;
+    }
+
+    return rb_process_status_new(ret, s, e);
 }
 
 /*
@@ -1432,14 +1432,19 @@ rb_pid_t https://github.com/ruby/ruby/blob/trunk/process.c#L1432
 rb_waitpid(rb_pid_t pid, int *st, int flags)
 {
     VALUE status = rb_process_status_wait(pid, flags);
-    if (NIL_P(status)) return -1;
+    if (NIL_P(status)) return 0;
 
     struct rb_process_status *data = RTYPEDDATA_DATA(status);
     pid = data->pid;
 
     if (st) *st = data->status;
 
-    GET_THREAD()->last_status = status;
+    if (pid == -1) {
+        errno = data->error;
+    }
+    else {
+        GET_THREAD()->last_status = status;
+    }
 
     return pid;
 }
diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb
index a114f27..d1b9d8a 100644
--- a/test/ruby/test_process.rb
+++ b/test/ruby/test_process.rb
@@ -1466,7 +1466,22 @@ class TestProcess < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_process.rb#L1466
   end
 
   def test_status_fail
-    assert_nil(Process::Status.wait($$))
+    ret = Process::Status.wait($$)
+    assert_instance_of(Process::Status, ret)
+    assert_equal(-1, ret.pid)
+  end
+
+
+  def test_status_wait
+    IO.popen([RUBY, "-e", "gets"], "w") do |io|
+      pid = io.pid
+      assert_nil(Process::Status.wait(pid, Process::WNOHANG))
+      io.puts
+      ret = Process::Status.wait(pid)
+      assert_instance_of(Process::Status, ret)
+      assert_equal(pid, ret.pid)
+      assert_predicate(ret, :exited?)
+    end
   end
 
   def test_wait_without_arg
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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