summaryrefslogtreecommitdiff
path: root/ext/io
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2020-10-11 16:09:51 +0900
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2021-11-16 20:25:43 +0900
commitdb71a04c2ec73f09fee01c85c6343175657f2078 (patch)
tree84608ffc50963c73e7640c050b330feba794277f /ext/io
parentd305ae5f045e839de183f7d575864b7718a2faa5 (diff)
[ruby/io-wait] Fix backward compatibility with earlier versions
https://github.com/ruby/io-wait/commit/898248931f
Diffstat (limited to 'ext/io')
-rw-r--r--ext/io/wait/extconf.rb1
-rw-r--r--ext/io/wait/wait.c114
2 files changed, 108 insertions, 7 deletions
diff --git a/ext/io/wait/extconf.rb b/ext/io/wait/extconf.rb
index b5d36c3fe3..d20ff4553f 100644
--- a/ext/io/wait/extconf.rb
+++ b/ext/io/wait/extconf.rb
@@ -2,6 +2,7 @@
require 'mkmf'
target = "io/wait"
+have_func("rb_io_wait")
unless macro_defined?("DOSISH", "#include <ruby.h>")
have_header(ioctl_h = "sys/ioctl.h") or ioctl_h = nil
fionread = %w[sys/ioctl.h sys/filio.h sys/socket.h].find do |h|
diff --git a/ext/io/wait/wait.c b/ext/io/wait/wait.c
index 512e4f6a80..8f0d16e168 100644
--- a/ext/io/wait/wait.c
+++ b/ext/io/wait/wait.c
@@ -40,6 +40,37 @@
#define FIONREAD_POSSIBLE_P(fd) ((void)(fd),Qtrue)
#endif
+#ifndef HAVE_RB_IO_WAIT
+static VALUE io_ready_p _((VALUE io));
+static VALUE io_wait_readable _((int argc, VALUE *argv, VALUE io));
+static VALUE io_wait_writable _((int argc, VALUE *argv, VALUE io));
+void Init_wait _((void));
+
+static struct timeval *
+get_timeout(int argc, VALUE *argv, struct timeval *timerec)
+{
+ VALUE timeout = Qnil;
+ rb_check_arity(argc, 0, 1);
+ if (!argc || NIL_P(timeout = argv[0])) {
+ return NULL;
+ }
+ else {
+ *timerec = rb_time_interval(timeout);
+ return timerec;
+ }
+}
+
+static int
+wait_for_single_fd(rb_io_t *fptr, int events, struct timeval *tv)
+{
+ int i = rb_wait_for_single_fd(fptr->fd, events, tv);
+ if (i < 0)
+ rb_sys_fail(0);
+ rb_io_check_closed(fptr);
+ return (i & events);
+}
+#endif
+
/*
* call-seq:
* io.nread -> int
@@ -51,12 +82,13 @@
static VALUE
io_nread(VALUE io)
{
- rb_io_t *fptr = NULL;
+ rb_io_t *fptr;
+ int len;
ioctl_arg n;
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
- int len = rb_io_read_pending(fptr);
+ len = rb_io_read_pending(fptr);
if (len > 0) return INT2FIX(len);
if (!FIONREAD_POSSIBLE_P(fptr->fd)) return INT2FIX(0);
if (ioctl(fptr->fd, FIONREAD, &n)) return INT2FIX(0);
@@ -64,6 +96,7 @@ io_nread(VALUE io)
return INT2FIX(0);
}
+#ifdef HAVE_RB_IO_WAIT
static VALUE
io_wait_event(VALUE io, int event, VALUE timeout)
{
@@ -82,6 +115,7 @@ io_wait_event(VALUE io, int event, VALUE timeout)
return Qfalse;
}
}
+#endif
/*
* call-seq:
@@ -94,12 +128,22 @@ static VALUE
io_ready_p(VALUE io)
{
rb_io_t *fptr;
+#ifndef HAVE_RB_IO_WAIT
+ struct timeval tv = {0, 0};
+#endif
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
if (rb_io_read_pending(fptr)) return Qtrue;
- return io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0));
+#ifndef HAVE_RB_IO_WAIT
+ if (wait_for_single_fd(fptr, RB_WAITFD_IN, &tv))
+ return Qtrue;
+#else
+ if (RTEST(io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0))))
+ return Qtrue;
+#endif
+ return Qfalse;
}
/*
@@ -115,17 +159,31 @@ io_ready_p(VALUE io)
static VALUE
io_wait_readable(int argc, VALUE *argv, VALUE io)
{
- rb_io_t *fptr = NULL;
+ rb_io_t *fptr;
+#ifndef HAVE_RB_IO_WAIT
+ struct timeval timerec;
+ struct timeval *tv;
+#endif
- RB_IO_POINTER(io, fptr);
+ GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
+#ifndef HAVE_RB_IO_WAIT
+ tv = get_timeout(argc, argv, &timerec);
+#endif
if (rb_io_read_pending(fptr)) return Qtrue;
+#ifndef HAVE_RB_IO_WAIT
+ if (wait_for_single_fd(fptr, RB_WAITFD_IN, tv)) {
+ return io;
+ }
+ return Qnil;
+#else
rb_check_arity(argc, 0, 1);
VALUE timeout = (argc == 1 ? argv[0] : Qnil);
return io_wait_event(io, RUBY_IO_READABLE, timeout);
+#endif
}
/*
@@ -139,17 +197,30 @@ io_wait_readable(int argc, VALUE *argv, VALUE io)
static VALUE
io_wait_writable(int argc, VALUE *argv, VALUE io)
{
- rb_io_t *fptr = NULL;
+ rb_io_t *fptr;
+#ifndef HAVE_RB_IO_WAIT
+ struct timeval timerec;
+ struct timeval *tv;
+#endif
- RB_IO_POINTER(io, fptr);
+ GetOpenFile(io, fptr);
rb_io_check_writable(fptr);
+#ifndef HAVE_RB_IO_WAIT
+ tv = get_timeout(argc, argv, &timerec);
+ if (wait_for_single_fd(fptr, RB_WAITFD_OUT, tv)) {
+ return io;
+ }
+ return Qnil;
+#else
rb_check_arity(argc, 0, 1);
VALUE timeout = (argc == 1 ? argv[0] : Qnil);
return io_wait_event(io, RUBY_IO_WRITABLE, timeout);
+#endif
}
+#ifdef HAVE_RB_IO_WAIT
/*
* call-seq:
* io.wait_priority -> true or false
@@ -173,6 +244,7 @@ io_wait_priority(int argc, VALUE *argv, VALUE io)
return io_wait_event(io, RUBY_IO_PRIORITY, timeout);
}
+#endif
static int
wait_mode_sym(VALUE mode)
@@ -228,6 +300,31 @@ wait_mode_sym(VALUE mode)
static VALUE
io_wait(int argc, VALUE *argv, VALUE io)
{
+#ifndef HAVE_RB_IO_WAIT
+ rb_io_t *fptr;
+ struct timeval timerec;
+ struct timeval *tv = NULL;
+ int event = 0;
+ int i;
+
+ GetOpenFile(io, fptr);
+ for (i = 0; i < argc; ++i) {
+ if (SYMBOL_P(argv[i])) {
+ event |= wait_mode_sym(argv[i]);
+ }
+ else {
+ *(tv = &timerec) = rb_time_interval(argv[i]);
+ }
+ }
+ /* rb_time_interval() and might_mode() might convert the argument */
+ rb_io_check_closed(fptr);
+ if (!event) event = RB_WAITFD_IN;
+ if ((event & RB_WAITFD_IN) && rb_io_read_pending(fptr))
+ return Qtrue;
+ if (wait_for_single_fd(fptr, event, tv))
+ return io;
+ return Qnil;
+#else
VALUE timeout = Qundef;
rb_io_event_t events = 0;
@@ -264,6 +361,7 @@ io_wait(int argc, VALUE *argv, VALUE io)
}
return io_wait_event(io, events, timeout);
+#endif
}
/*
@@ -284,5 +382,7 @@ Init_wait(void)
rb_define_method(rb_cIO, "wait_readable", io_wait_readable, -1);
rb_define_method(rb_cIO, "wait_writable", io_wait_writable, -1);
+#ifdef HAVE_RB_IO_WAIT
rb_define_method(rb_cIO, "wait_priority", io_wait_priority, -1);
+#endif
}