about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--ext/kgio/poll.c8
-rw-r--r--test/test_poll.rb20
2 files changed, 25 insertions, 3 deletions
diff --git a/ext/kgio/poll.c b/ext/kgio/poll.c
index 614d939..2f101d1 100644
--- a/ext/kgio/poll.c
+++ b/ext/kgio/poll.c
@@ -100,6 +100,7 @@ static int io_to_pollfd_i(VALUE key, VALUE value, VALUE args)
 
 static void hash2pollfds(struct poll_args *a)
 {
+        a->nfds = 0;
         a->fds = xmalloc(sizeof(struct pollfd) * RHASH_SIZE(a->ios));
         a->fd_to_io = st_init_numtable();
         rb_hash_foreach(a->ios, io_to_pollfd_i, (VALUE)a);
@@ -140,14 +141,16 @@ static VALUE do_poll(VALUE args)
         int nr;
 
         Check_Type(a->ios, T_HASH);
-        hash2pollfds(a);
 
 retry:
+        hash2pollfds(a);
         nr = (int)rb_thread_blocking_region(nogvl_poll, a, RUBY_UBF_IO, NULL);
         if (nr < 0) {
                 if (interrupted()) {
-                        if (retryable(a))
+                        if (retryable(a)) {
+                                poll_free(args);
                                 goto retry;
+                        }
                         return Qnil;
                 }
                 rb_sys_fail("poll");
@@ -196,7 +199,6 @@ static VALUE s_poll(int argc, VALUE *argv, VALUE self)
 
         rb_scan_args(argc, argv, "11", &a.ios, &timeout);
         a.timeout = num2timeout(timeout);
-        a.nfds = 0;
         a.fds = NULL;
         a.fd_to_io = NULL;
 
diff --git a/test/test_poll.rb b/test/test_poll.rb
index 1c92223..d99e5aa 100644
--- a/test/test_poll.rb
+++ b/test/test_poll.rb
@@ -70,4 +70,24 @@ class TestPoll < Test::Unit::TestCase
     ensure
       trap(:USR1, orig)
   end
+
+  def test_poll_EINTR_changed
+    ok = false
+    orig = trap(:USR1) { ok = true }
+    pollset = { @rd => Kgio::POLLIN }
+    thr = Thread.new do
+      sleep 0.100
+      pollset[@wr] = Kgio::POLLOUT
+      Process.kill(:USR1, $$)
+    end
+    t0 = Time.now
+    res = Kgio.poll(pollset, 1000)
+    diff = Time.now - t0
+    thr.join
+    assert_equal({@wr => Kgio::POLLOUT}, res)
+    assert diff < 1.0, "diff=#{diff}"
+    assert ok
+    ensure
+      trap(:USR1, orig)
+  end
 end if Kgio.respond_to?(:poll)