diff options
-rw-r--r-- | ext/kgio/poll.c | 8 | ||||
-rw-r--r-- | test/test_poll.rb | 20 |
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) |