Class: God::KQueueHandler

Inherits:
Object
  • Object
show all
Defined in:
lib/god/event_handlers/kqueue_handler.rb,
ext/god/kqueue_handler.c
more...

Constant Summary collapse

EVENT_SYSTEM =
"kqueue"

Class Method Summary collapse

Class Method Details

.event_mask(sym) ⇒ Object

[View source]

23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'ext/god/kqueue_handler.c', line 23

VALUE
kqh_event_mask(VALUE klass, VALUE sym)
{
  ID id = SYM2ID(sym);
  if (proc_exit == id) {
    return UINT2NUM(NOTE_EXIT);
  } else if (proc_fork == id) {
    return UINT2NUM(NOTE_FORK);
  } else {
    rb_raise(rb_eNotImpError, "Event `%s` not implemented", rb_id2name(id));
  }
  
  return Qnil;
}

.events_mask(events) ⇒ Object

[View source]

11
12
13
14
15
# File 'lib/god/event_handlers/kqueue_handler.rb', line 11

def self.events_mask(events)
  events.inject(0) do |mask, event|
    mask |= event_mask(event)
  end
end

.handle_eventsObject

[View source]

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'ext/god/kqueue_handler.c', line 59

VALUE
kqh_handle_events()
{
  int nevents, i, num_to_fetch;
  struct kevent *events;
  fd_set read_set;
  
  FD_ZERO(&read_set);
  FD_SET(kq, &read_set);
  
  // Don't actually run this method until we've got an event
  rb_thread_select(kq + 1, &read_set, NULL, NULL, NULL);  
  
  // Grabbing num_events once for thread safety
  num_to_fetch = num_events;
  events = (struct kevent*)malloc(num_to_fetch * sizeof(struct kevent));
  
  if (NULL == events) {
    rb_raise(rb_eStandardError, strerror(errno));
  }
  
  nevents = kevent(kq, NULL, 0, events, num_to_fetch, NULL);
  
  if (-1 == nevents) {
    free(events);
    rb_raise(rb_eStandardError, strerror(errno));
  } else {
    for (i = 0; i < nevents; i++) {
      if (events[i].fflags & NOTE_EXIT) {
        rb_funcall(cEventHandler, m_call, 2, INT2NUM(events[i].ident), ID2SYM(proc_exit));
      } else if (events[i].fflags & NOTE_FORK) {
        rb_funcall(cEventHandler, m_call, 2, INT2NUM(events[i].ident), ID2SYM(proc_fork));
      }
    }
  }
  
  free(events);

  return INT2FIX(nevents);
}

.monitor_process(pid, mask) ⇒ Object

[View source]

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'ext/god/kqueue_handler.c', line 39

VALUE
kqh_monitor_process(VALUE klass, VALUE pid, VALUE mask)
{
  struct kevent new_event;
  ID event;
  
  u_int fflags = NUM2UINT(mask);
  
  EV_SET(&new_event, FIX2UINT(pid), EVFILT_PROC,
         EV_ADD | EV_ENABLE, fflags, 0, 0);
  
  if (-1 == kevent(kq, &new_event, 1, NULL, 0, NULL)) {
    rb_raise(rb_eStandardError, strerror(errno));
  }
  
  num_events = NUM_EVENTS;
  
  return Qnil;
}

.register_process(pid, events) ⇒ Object

[View source]

7
8
9
# File 'lib/god/event_handlers/kqueue_handler.rb', line 7

def self.register_process(pid, events)
  monitor_process(pid, events_mask(events))
end