ruby-changes:51214
From: normal <ko1@a...>
Date: Tue, 15 May 2018 08:51:40 +0900 (JST)
Subject: [ruby-changes:51214] normal:r63421 (trunk): test_wait_for_single_fd: ensure this works with kqueue
normal 2018-05-15 08:51:35 +0900 (Tue, 15 May 2018) New Revision: 63421 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=63421 Log: test_wait_for_single_fd: ensure this works with kqueue Regardless of future features, this needs to work with kqueue descriptors across platforms. Today this will be useful for 3rd-party libraries using kqueue. In the future, Ruby may use kqueue natively and we shall ensure we can wait on it. Modified files: trunk/ext/-test-/wait_for_single_fd/extconf.rb trunk/ext/-test-/wait_for_single_fd/wait_for_single_fd.c trunk/test/-ext-/wait_for_single_fd/test_wait_for_single_fd.rb Index: test/-ext-/wait_for_single_fd/test_wait_for_single_fd.rb =================================================================== --- test/-ext-/wait_for_single_fd/test_wait_for_single_fd.rb (revision 63420) +++ test/-ext-/wait_for_single_fd/test_wait_for_single_fd.rb (revision 63421) @@ -52,5 +52,8 @@ class TestWaitForSingleFD < Test::Unit:: https://github.com/ruby/ruby/blob/trunk/test/-ext-/wait_for_single_fd/test_wait_for_single_fd.rb#L52 end end - + def test_wait_for_kqueue + skip 'no kqueue' unless IO.respond_to?(:kqueue_test_wait) + assert_equal RB_WAITFD_IN, IO.kqueue_test_wait + end end Index: ext/-test-/wait_for_single_fd/wait_for_single_fd.c =================================================================== --- ext/-test-/wait_for_single_fd/wait_for_single_fd.c (revision 63420) +++ ext/-test-/wait_for_single_fd/wait_for_single_fd.c (revision 63421) @@ -19,6 +19,67 @@ wait_for_single_fd(VALUE ign, VALUE fd, https://github.com/ruby/ruby/blob/trunk/ext/-test-/wait_for_single_fd/wait_for_single_fd.c#L19 return INT2NUM(rc); } +#ifdef HAVE_KQUEUE +/* ensure rb_wait_for_single_fd works on kqueue descriptors */ +#include <sys/types.h> +#include <sys/time.h> +#include <sys/event.h> +static VALUE +kqueue_test_wait(VALUE klass) +{ + int kqfd = -1; + int p[2] = { -1, -1 }; + struct timeval tv = { 0, 0 }; + const struct timespec ts = { 1, 0 }; + struct kevent kev; + const char *msg; + VALUE ret = Qfalse; + int e = 0; + int n; + + msg = "pipe"; + if (rb_cloexec_pipe(p) < 0) goto err; + + msg = "kqueue"; + kqfd = kqueue(); + if (kqfd < 0) goto err; + + n = rb_wait_for_single_fd(kqfd, RB_WAITFD_IN, &tv); + if (n != 0) { + msg = "spurious wakeup"; + errno = 0; + goto err; + } + + msg = "write"; + if (write(p[1], "", 1) < 0) goto err; + + EV_SET(&kev, p[0], EVFILT_READ, EV_ADD, 0, 0, 0); + + msg = "kevent"; + n = kevent(kqfd, &kev, 1, &kev, 1, &ts); + if (n < 0) goto err; + msg = NULL; + if (n == 1) { + n = rb_wait_for_single_fd(kqfd, RB_WAITFD_IN, &tv); + ret = INT2NUM(n); + } + else { + rb_warn("kevent did not return readiness"); + } +err: + if (msg) e = errno; + if (p[0] >= 0) close(p[0]); + if (p[1] >= 0) close(p[1]); + if (kqfd >= 0) close(kqfd); + if (msg) { + if (e) rb_syserr_fail(e, msg); + rb_raise(rb_eRuntimeError, msg); + } + return ret; +} +#endif /* HAVE_KQUEUE */ + void Init_wait_for_single_fd(void) { @@ -27,4 +88,7 @@ Init_wait_for_single_fd(void) https://github.com/ruby/ruby/blob/trunk/ext/-test-/wait_for_single_fd/wait_for_single_fd.c#L88 rb_define_const(rb_cObject, "RB_WAITFD_PRI", INT2NUM(RB_WAITFD_PRI)); rb_define_singleton_method(rb_cIO, "wait_for_single_fd", wait_for_single_fd, 3); +#ifdef HAVE_KQUEUE + rb_define_singleton_method(rb_cIO, "kqueue_test_wait", kqueue_test_wait, 0); +#endif } Index: ext/-test-/wait_for_single_fd/extconf.rb =================================================================== --- ext/-test-/wait_for_single_fd/extconf.rb (revision 63420) +++ ext/-test-/wait_for_single_fd/extconf.rb (revision 63421) @@ -1,2 +1,4 @@ https://github.com/ruby/ruby/blob/trunk/ext/-test-/wait_for_single_fd/extconf.rb#L1 # frozen_string_literal: false +headers = %w(sys/types.h sys/time.h sys/event.h).select { |h| have_header(h) } +have_func('kqueue', headers) create_makefile("-test-/wait_for_single_fd") -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/