ext/sleepy_penguin/kqueue.c in sleepy_penguin-3.5.0 vs ext/sleepy_penguin/kqueue.c in sleepy_penguin-3.5.1
- old
+ new
@@ -16,10 +16,13 @@
/* not bothering with overflow checking for backwards compat */
#ifndef RARRAY_LENINT
# define RARRAY_LENINT(ary) (int)RARRAY_LEN(ary)
#endif
+#ifndef RARRAY_CONST_PTR
+# define RARRAY_CONST_PTR(ary) RARRAY_PTR(ary)
+#endif
#ifndef NUM2SHORT
# define NUM2SHORT(n) (short)NUM2INT(n)
#endif
#ifndef NUM2USHORT
# define NUM2USHORT(n) (short)NUM2UINT(n)
@@ -108,10 +111,11 @@
*/
static VALUE s_new(VALUE klass)
{
VALUE rv;
int fd = kqueue();
+ int flags;
if (fd < 0) {
/*
* ENOMEM/EMFILE/ENFILE are the only documented errors
* for kqueue(), hope GC can give us some space to retry:
@@ -120,13 +124,16 @@
fd = kqueue();
if (fd < 0)
rb_sys_fail("kqueue");
}
+ flags = fcntl(fd, F_GETFD);
+ if (flags != -1)
+ fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
+
rv = INT2FIX(fd);
- /* This will set FD_CLOEXEC on Ruby 2.0.0+: */
return rb_call_super(1, &rv);
}
static void yield_kevent(struct kevent *event)
{
@@ -227,84 +234,110 @@
} while (nevents < 0 && kevent_resume_p(&expire_at, kpt));
return kevent_result(kpt, (int)nevents);
}
-static void event_set(struct kevent *event, VALUE *chg)
+#if defined(HAVE_RB_STRUCT_SIZE) && defined(RSTRUCT_GET)
+static void ev_set_struct(struct kevent *ev, VALUE event)
{
- uintptr_t ident = (uintptr_t)NUM2ULONG(chg[0]);
- short filter = NUM2SHORT(chg[1]);
- unsigned short flags = NUM2USHORT(chg[2]);
- unsigned fflags = (unsigned)NUM2UINT(chg[3]);
- intptr_t data = (intptr_t)NUM2LONG(chg[4]);
- void *udata = (void *)chg[5];
+ if (rb_struct_size(event) == INT2NUM(6)) {
+ uintptr_t ident = (uintptr_t)NUM2ULONG(RSTRUCT_GET(event, 0));
+ short filter = NUM2SHORT(RSTRUCT_GET(event, 1));
+ unsigned short flags = NUM2USHORT(RSTRUCT_GET(event, 2));
+ unsigned fflags = (unsigned)NUM2UINT(RSTRUCT_GET(event, 3));
+ intptr_t data = (intptr_t)NUM2LONG(RSTRUCT_GET(event, 4));
+ void *udata = (void *)RSTRUCT_GET(event, 5);
- EV_SET(event, ident, filter, flags, fflags, data, udata);
+ EV_SET(ev, ident, filter, flags, fflags, data, udata);
+ } else {
+ rb_raise(rb_eTypeError, "unsupported struct in changelist");
+ }
}
+#elif RBX_STRUCT == 0 && defined(RSTRUCT_LEN) && defined(RSTRUCT_PTR)
+/* legacy MRI */
+static void ev_set_struct(struct kevent *ev, VALUE event)
+{
+ long len = RSTRUCT_LEN(*event);
+ if (len == 6) {
+ const VALUE *ptr = RSTRUCT_PTR(*event);
+ uintptr_t ident = (uintptr_t)NUM2ULONG(ptr[0]);
+ short filter = NUM2SHORT(ptr[1]);
+ unsigned short flags = NUM2USHORT(ptr[2]);
+ unsigned fflags = (unsigned)NUM2UINT(ptr[3]);
+ intptr_t data = (intptr_t)NUM2LONG(ptr[4]);
+ void *udata = (void *)ptr[5];
+ EV_SET(event, ident, filter, flags, fflags, data, udata);
+ } else {
+ rb_raise(rb_eTypeError, "unsupported struct in changelist");
+ }
+}
+#else
+static void ev_set_struct(struct kevent *ev, VALUE event)
+{
+ rb_raise(rb_eTypeError, "unsupported struct in changelist");
+}
+#endif
+
+static void ev_set_ary(struct kevent *ev, VALUE event)
+{
+ long len = RARRAY_LEN(event);
+ const VALUE *ptr = RARRAY_CONST_PTR(event);
+
+ if (len == 6) {
+ uintptr_t ident = (uintptr_t)NUM2ULONG(ptr[0]);
+ short filter = NUM2SHORT(ptr[1]);
+ unsigned short flags = NUM2USHORT(ptr[2]);
+ unsigned fflags = (unsigned)NUM2UINT(ptr[3]);
+ intptr_t data = (intptr_t)NUM2LONG(ptr[4]);
+ void *udata = (void *)ptr[5];
+
+ EV_SET(ev, ident, filter, flags, fflags, data, udata);
+ return;
+ }
+ rb_raise(rb_eTypeError,
+ "changelist must be an array of 6-element arrays or structs");
+}
+
/* sets ptr and len */
-static void unpack_event(VALUE **ptr, VALUE *len, VALUE *event)
+static void unpack_event(struct kevent *ev, VALUE event)
{
- switch (TYPE(*event)) {
+ switch (TYPE(event)) {
case T_STRUCT:
if (RBX_STRUCT) {
- *event = rb_funcall(*event, rb_intern("to_a"), 0, 0);
+ event = rb_funcall(event, rb_intern("to_a"), 0, 0);
/* fall-through to T_ARRAY */
} else {
- *len = RSTRUCT_LEN(*event);
- *ptr = RSTRUCT_PTR(*event);
+ ev_set_struct(ev, event);
return;
}
case T_ARRAY:
- *len = RARRAY_LEN(*event);
- *ptr = RARRAY_PTR(*event);
- return;
+ ev_set_ary(ev, event);
default:
rb_raise(rb_eTypeError, "unsupported type in changelist");
}
}
static void ary2eventlist(struct kevent *events, VALUE changelist)
{
- VALUE *chg = RARRAY_PTR(changelist);
+ const VALUE *chg = RARRAY_CONST_PTR(changelist);
long i = RARRAY_LEN(changelist);
- VALUE event;
- for (; --i >= 0; chg++) {
- VALUE clen;
- VALUE *cptr;
-
- event = *chg;
- unpack_event(&cptr, &clen, &event);
- if (clen != 6)
- goto out_list;
- event_set(events++, cptr);
- }
- return;
-out_list:
- rb_raise(rb_eTypeError,
- "changelist must be an array of 6-element arrays or structs");
+ for (; --i >= 0; chg++)
+ unpack_event(events++, *chg);
}
/*
* Convert an Ruby representation of the changelist to "struct kevent"
*/
static void changelist_prepare(struct kevent *events, VALUE changelist)
{
- VALUE *cptr;
- VALUE clen;
- VALUE event;
-
switch (TYPE(changelist)) {
case T_ARRAY:
ary2eventlist(events, changelist);
return;
- case T_STRUCT:
- event = changelist;
- unpack_event(&cptr, &clen, &event);
- if (clen != 6)
- rb_raise(rb_eTypeError, "event is not a Kevent struct");
- event_set(events, cptr);
+ case T_STRUCT: /* single event */
+ unpack_event(events, changelist);
return;
default:
rb_bug("changelist_prepare not type filtered by sp_kevent");
}
}