about summary refs log tree commit homepage
path: root/ext
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2013-03-01 19:50:27 +0000
committerEric Wong <normalperson@yhbt.net>2013-03-01 19:50:27 +0000
commit2f5c82c26aeaf3536deace3521097d3e9eaefc20 (patch)
treefe3234161ee0156ccd1ca137ad932699303b298e /ext
parentc217412e59dedf0fa98069815c395339007ede6b (diff)
downloadsleepy_penguin-2f5c82c26aeaf3536deace3521097d3e9eaefc20.tar.gz
The file descriptor may be closed while GVL is released,
so we must reload the descriptor before and after calling
rb_io_wait_*able functions.

We reload before calling rb_io_wait_*able because the GVL was
released for the function call (read/write) which triggered
EAGAIN.

We reload after calling rb_io_wait_*able because
rb_io_wait_*able releases the GVL, too.
Diffstat (limited to 'ext')
-rw-r--r--ext/sleepy_penguin/eventfd.c4
-rw-r--r--ext/sleepy_penguin/inotify.c9
-rw-r--r--ext/sleepy_penguin/signalfd.c2
-rw-r--r--ext/sleepy_penguin/sleepy_penguin.h4
-rw-r--r--ext/sleepy_penguin/timerfd.c2
-rw-r--r--ext/sleepy_penguin/util.c11
6 files changed, 22 insertions, 10 deletions
diff --git a/ext/sleepy_penguin/eventfd.c b/ext/sleepy_penguin/eventfd.c
index 9d75c91..3ba8397 100644
--- a/ext/sleepy_penguin/eventfd.c
+++ b/ext/sleepy_penguin/eventfd.c
@@ -91,7 +91,7 @@ retry:
         if (w == -1) {
                 if (errno == EAGAIN && RTEST(nonblock))
                         return Qfalse;
-                if (rb_io_wait_writable(x.fd))
+                if (rb_sp_wait(rb_io_wait_writable, self, &x.fd))
                         goto retry;
                 rb_sys_fail("write(eventfd)");
         }
@@ -127,7 +127,7 @@ retry:
         if (w == -1) {
                 if (errno == EAGAIN && RTEST(nonblock))
                         return Qnil;
-                if (rb_io_wait_readable(x.fd = rb_sp_fileno(self)))
+                if (rb_sp_wait(rb_io_wait_readable, self, &x.fd))
                         goto retry;
                 rb_sys_fail("read(eventfd)");
         }
diff --git a/ext/sleepy_penguin/inotify.c b/ext/sleepy_penguin/inotify.c
index 7d83aca..f858dc4 100644
--- a/ext/sleepy_penguin/inotify.c
+++ b/ext/sleepy_penguin/inotify.c
@@ -196,13 +196,10 @@ static VALUE take(int argc, VALUE *argv, VALUE self)
                         args.ptr = (struct inotify_event *)RSTRING_PTR(buf);
                         args.len = newlen;
                 } else if (r < 0) {
-                        if (errno == EAGAIN && RTEST(nonblock)) {
+                        if (errno == EAGAIN && RTEST(nonblock))
                                 return Qnil;
-                        } else {
-                                args.fd = rb_sp_fileno(self);
-                                if (!rb_io_wait_readable(args.fd))
-                                        rb_sys_fail("read(inotify)");
-                        }
+                        if (!rb_sp_wait(rb_io_wait_readable, self, &args.fd))
+                                rb_sys_fail("read(inotify)");
                 } else {
                         /* buffer in userspace to minimize read() calls */
                         end = (struct inotify_event *)((char *)args.ptr + r);
diff --git a/ext/sleepy_penguin/signalfd.c b/ext/sleepy_penguin/signalfd.c
index 59eb05f..c2c9419 100644
--- a/ext/sleepy_penguin/signalfd.c
+++ b/ext/sleepy_penguin/signalfd.c
@@ -198,7 +198,7 @@ retry:
         if (r == -1) {
                 if (errno == EAGAIN && RTEST(nonblock))
                         return Qnil;
-                if (rb_io_wait_readable(fd = rb_sp_fileno(self)))
+                if (rb_sp_wait(rb_io_wait_readable, self, &fd))
                         goto retry;
                 rb_sys_fail("read(signalfd)");
         }
diff --git a/ext/sleepy_penguin/sleepy_penguin.h b/ext/sleepy_penguin/sleepy_penguin.h
index 2b2d063..bd4a4ca 100644
--- a/ext/sleepy_penguin/sleepy_penguin.h
+++ b/ext/sleepy_penguin/sleepy_penguin.h
@@ -40,4 +40,8 @@ VALUE rb_thread_io_blocking_region(rb_blocking_function_t *, void *, int);
 
 #define NODOC_CONST(klass,name,value) \
   rb_define_const((klass),(name),(value))
+
+
+typedef int rb_sp_waitfn(int fd);
+int rb_sp_wait(rb_sp_waitfn waiter, VALUE obj, int *fd);
 #endif /* SLEEPY_PENGUIN_H */
diff --git a/ext/sleepy_penguin/timerfd.c b/ext/sleepy_penguin/timerfd.c
index 1f2d516..b9e3999 100644
--- a/ext/sleepy_penguin/timerfd.c
+++ b/ext/sleepy_penguin/timerfd.c
@@ -129,7 +129,7 @@ retry:
         if (r == -1) {
                 if (errno == EAGAIN && RTEST(nonblock))
                         return Qnil;
-                if (rb_io_wait_readable(fd = rb_sp_fileno(self)))
+                if (rb_sp_wait(rb_io_wait_readable, self, &fd))
                         goto retry;
                 rb_sys_fail("read(timerfd)");
         }
diff --git a/ext/sleepy_penguin/util.c b/ext/sleepy_penguin/util.c
index 10fd404..301cc92 100644
--- a/ext/sleepy_penguin/util.c
+++ b/ext/sleepy_penguin/util.c
@@ -141,3 +141,14 @@ VALUE rb_sp_io_region(rb_blocking_function_t *func, void *data)
         return rv;
 }
 #endif
+
+int rb_sp_wait(rb_sp_waitfn waiter, VALUE obj, int *fd)
+{
+        /*
+         * we need to check the fileno before and after waiting, a close()
+         * could've happened at any time (especially when outside of GVL).
+         */
+        int rc = waiter(rb_sp_fileno(obj));
+        *fd = rb_sp_fileno(obj);
+        return rc;
+}