ext/sleepy_penguin/inotify.c in sleepy_penguin-3.4.1 vs ext/sleepy_penguin/inotify.c in sleepy_penguin-3.5.0
- old
+ new
@@ -24,14 +24,12 @@
rb_scan_args(argc, argv, "01", &_flags);
flags = rb_sp_get_flags(klass, _flags, RB_SP_CLOEXEC(IN_CLOEXEC));
fd = inotify_init1(flags);
if (fd < 0) {
- if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
- rb_gc();
+ if (rb_sp_gc_for_fd(errno))
fd = inotify_init1(flags);
- }
if (fd < 0)
rb_sys_fail("inotify_init1");
}
rv = INT2FIX(fd);
@@ -134,12 +132,15 @@
return rb_struct_new(cEvent, wd, mask, cookie, name);
}
struct inread_args {
+ VALUE self;
int fd;
+ int nonblock_p;
size_t size;
+ VALUE tmp;
void *buf;
};
static VALUE inread(void *ptr)
{
@@ -158,10 +159,11 @@
if (ioctl(args->fd, FIONREAD, &newlen) != 0)
rb_sys_fail("ioctl(inotify,FIONREAD)");
if (newlen > 0) {
args->size = (size_t)newlen;
+ rb_sp_puttlsbuf((VALUE)args->buf);
args->buf = rb_sp_gettlsbuf(&args->size);
}
if (newlen == 0) /* race: some other thread grabbed the data */
return;
@@ -169,66 +171,76 @@
rb_raise(rb_eRuntimeError,
"ioctl(inotify,FIONREAD) returned negative length: %d",
newlen);
}
-/*
- * call-seq:
- * ino.take([nonblock]) -> Inotify::Event or nil
- *
- * Returns the next Inotify::Event processed. May return +nil+ if +nonblock+
- * is +true+.
- */
-static VALUE take(int argc, VALUE *argv, VALUE self)
+static VALUE do_take(VALUE p)
{
- struct inread_args args;
- VALUE tmp = rb_ivar_get(self, id_inotify_tmp);
- struct inotify_event *e, *end;
- ssize_t r;
+ struct inread_args *args = (struct inread_args *)p;
VALUE rv = Qnil;
- VALUE nonblock;
+ struct inotify_event *e, *end;
- if (RARRAY_LEN(tmp) > 0)
- return rb_ary_shift(tmp);
-
- rb_scan_args(argc, argv, "01", &nonblock);
-
- args.fd = rb_sp_fileno(self);
- args.size = 128;
- args.buf = rb_sp_gettlsbuf(&args.size);
-
- if (RTEST(nonblock))
- rb_sp_set_nonblock(args.fd);
- else
- blocking_io_prepare(args.fd);
+ args->buf = rb_sp_gettlsbuf(&args->size);
do {
- r = (ssize_t)rb_sp_fd_region(inread, &args, args.fd);
+ ssize_t r = (ssize_t)rb_sp_fd_region(inread, args, args->fd);
if (r == 0 /* Linux < 2.6.21 */
||
(r < 0 && errno == EINVAL) /* Linux >= 2.6.21 */
) {
- resize_internal_buffer(&args);
+ resize_internal_buffer(args);
} else if (r < 0) {
- if (errno == EAGAIN && RTEST(nonblock))
+ if (errno == EAGAIN && args->nonblock_p)
return Qnil;
- if (!rb_sp_wait(rb_io_wait_readable, self, &args.fd))
+ if (!rb_sp_wait(rb_io_wait_readable, args->self,
+ &args->fd))
rb_sys_fail("read(inotify)");
} else {
/* buffer in userspace to minimize read() calls */
- end = (struct inotify_event *)((char *)args.buf + r);
- for (e = args.buf; e < end; ) {
+ end = (struct inotify_event *)((char *)args->buf + r);
+ for (e = args->buf; e < end; ) {
VALUE event = event_new(e);
if (NIL_P(rv))
rv = event;
else
- rb_ary_push(tmp, event);
+ rb_ary_push(args->tmp, event);
e = (struct inotify_event *)
((char *)e + event_len(e));
}
}
} while (NIL_P(rv));
return rv;
+}
+
+/*
+ * call-seq:
+ * ino.take([nonblock]) -> Inotify::Event or nil
+ *
+ * Returns the next Inotify::Event processed. May return +nil+ if +nonblock+
+ * is +true+.
+ */
+static VALUE take(int argc, VALUE *argv, VALUE self)
+{
+ struct inread_args args;
+ VALUE nonblock;
+
+ args.tmp = rb_ivar_get(self, id_inotify_tmp);
+ if (RARRAY_LEN(args.tmp) > 0)
+ return rb_ary_shift(args.tmp);
+
+ rb_scan_args(argc, argv, "01", &nonblock);
+
+ args.self = self;
+ args.fd = rb_sp_fileno(self);
+ args.size = 128;
+ args.nonblock_p = RTEST(nonblock);
+
+ if (args.nonblock_p)
+ rb_sp_set_nonblock(args.fd);
+
+ args.buf = 0;
+ return rb_ensure(do_take, (VALUE)&args,
+ rb_sp_puttlsbuf, (VALUE)args.buf);
}
/*
* call-seq:
* inotify_event.events => [ :MOVED_TO, ... ]