diff options
author | Eric Wong <normalperson@yhbt.net> | 2013-03-01 19:50:27 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2013-03-01 19:50:27 +0000 |
commit | 2f5c82c26aeaf3536deace3521097d3e9eaefc20 (patch) | |
tree | fe3234161ee0156ccd1ca137ad932699303b298e /ext | |
parent | c217412e59dedf0fa98069815c395339007ede6b (diff) | |
download | sleepy_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.c | 4 | ||||
-rw-r--r-- | ext/sleepy_penguin/inotify.c | 9 | ||||
-rw-r--r-- | ext/sleepy_penguin/signalfd.c | 2 | ||||
-rw-r--r-- | ext/sleepy_penguin/sleepy_penguin.h | 4 | ||||
-rw-r--r-- | ext/sleepy_penguin/timerfd.c | 2 | ||||
-rw-r--r-- | ext/sleepy_penguin/util.c | 11 |
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; +} |