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, ... ]