1 #if defined(__FreeBSD__) || defined(__APPLE__)
9 static VALUE cKQueueHandler
;
10 static VALUE cEventHandler
;
16 static ID m_deregister
;
21 #define NUM_EVENTS FIX2INT(rb_funcall(rb_cv_get(cEventHandler, "@@actions"), m_size, 0))
24 kqh_event_mask(VALUE klass
, VALUE sym
)
27 if (proc_exit
== id
) {
28 return UINT2NUM(NOTE_EXIT
);
29 } else if (proc_fork
== id
) {
30 return UINT2NUM(NOTE_FORK
);
32 rb_raise(rb_eNotImpError
, "Event `%s` not implemented", rb_id2name(id
));
40 kqh_monitor_process(VALUE klass
, VALUE pid
, VALUE mask
)
42 struct kevent new_event
;
45 u_int fflags
= NUM2UINT(mask
);
47 EV_SET(&new_event
, FIX2UINT(pid
), EVFILT_PROC
,
48 EV_ADD
| EV_ENABLE
, fflags
, 0, 0);
50 if (-1 == kevent(kq
, &new_event
, 1, NULL
, 0, NULL
)) {
51 rb_raise(rb_eStandardError
, strerror(errno
));
54 num_events
= NUM_EVENTS
;
62 int nevents
, i
, num_to_fetch
;
63 struct kevent
*events
;
67 FD_SET(kq
, &read_set
);
69 // Don't actually run this method until we've got an event
70 rb_thread_select(kq
+ 1, &read_set
, NULL
, NULL
, NULL
);
72 // Grabbing num_events once for thread safety
73 num_to_fetch
= num_events
;
74 events
= (struct kevent
*)malloc(num_to_fetch
* sizeof(struct kevent
));
77 rb_raise(rb_eStandardError
, strerror(errno
));
80 nevents
= kevent(kq
, NULL
, 0, events
, num_to_fetch
, NULL
);
83 rb_raise(rb_eStandardError
, strerror(errno
));
85 for (i
= 0; i
< nevents
; i
++) {
86 if (events
[i
].fflags
& NOTE_EXIT
) {
87 rb_funcall(cEventHandler
, m_call
, 2, INT2NUM(events
[i
].ident
), ID2SYM(proc_exit
));
88 } else if (events
[i
].fflags
& NOTE_FORK
) {
89 rb_funcall(cEventHandler
, m_call
, 2, INT2NUM(events
[i
].ident
), ID2SYM(proc_fork
));
96 return INT2FIX(nevents
);
100 Init_kqueue_handler_ext()
105 rb_raise(rb_eStandardError
, "kqueue initilization failed");
108 proc_exit
= rb_intern("proc_exit");
109 proc_fork
= rb_intern("proc_fork");
110 m_call
= rb_intern("call");
111 m_size
= rb_intern("size");
112 m_deregister
= rb_intern("deregister");
114 mGod
= rb_const_get(rb_cObject
, rb_intern("God"));
115 cEventHandler
= rb_const_get(mGod
, rb_intern("EventHandler"));
116 cKQueueHandler
= rb_define_class_under(mGod
, "KQueueHandler", rb_cObject
);
117 rb_define_singleton_method(cKQueueHandler
, "monitor_process", kqh_monitor_process
, 2);
118 rb_define_singleton_method(cKQueueHandler
, "handle_events", kqh_handle_events
, 0);
119 rb_define_singleton_method(cKQueueHandler
, "event_mask", kqh_event_mask
, 1);