god 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt CHANGED
@@ -1,4 +1,12 @@
1
- == 1.0.0 / 2007-06-11
1
+ == 0.2.0
2
+
3
+ * Rewrote innards to use a state and event based lifecycle
4
+ * Basic support for events via kqueue (bsd/darwin) and netlink/pec (linux) [kevinclark]
5
+ * Added advanced syntax (simple syntax calls advanced api underneath)
6
+ * Condition returns have changed meaning. With simple syntax, a true return activates block
7
+ * Updated http://god.rubygorge.org with updated simple config and new advanced config
8
+
9
+ == 0.1.0 / 2007-07-07
2
10
 
3
11
  * 1 major enhancement
4
12
  * Birthday!
data/Manifest.txt CHANGED
@@ -5,6 +5,10 @@ Rakefile
5
5
  bin/god
6
6
  examples/gravatar.god
7
7
  examples/local.god
8
+ ext/god/Makefile
9
+ ext/god/extconf.rb
10
+ ext/god/kqueue_handler.c
11
+ ext/god/netlink_handler.c
8
12
  lib/god.rb
9
13
  lib/god/base.rb
10
14
  lib/god/behavior.rb
@@ -13,22 +17,30 @@ lib/god/condition.rb
13
17
  lib/god/conditions/always.rb
14
18
  lib/god/conditions/cpu_usage.rb
15
19
  lib/god/conditions/memory_usage.rb
16
- lib/god/conditions/process_not_running.rb
20
+ lib/god/conditions/process_exits.rb
21
+ lib/god/conditions/process_running.rb
17
22
  lib/god/conditions/timeline.rb
18
23
  lib/god/errors.rb
24
+ lib/god/event_handler.rb
25
+ lib/god/event_handlers/kqueue_handler.rb
26
+ lib/god/event_handlers/netlink_handler.rb
27
+ lib/god/hub.rb
19
28
  lib/god/meddle.rb
29
+ lib/god/metric.rb
20
30
  lib/god/reporter.rb
21
31
  lib/god/server.rb
22
32
  lib/god/system/process.rb
23
33
  lib/god/timer.rb
24
34
  lib/god/watch.rb
25
35
  test/configs/real.rb
36
+ test/configs/test.rb
26
37
  test/helper.rb
27
38
  test/suite.rb
28
39
  test/test_behavior.rb
29
40
  test/test_condition.rb
30
41
  test/test_god.rb
31
42
  test/test_meddle.rb
43
+ test/test_metric.rb
32
44
  test/test_reporter.rb
33
45
  test/test_server.rb
34
46
  test/test_system_process.rb
data/README.txt CHANGED
@@ -1,5 +1,7 @@
1
1
  god
2
2
  by Tom Preston-Werner
3
+ Kevin Clark (kqueue/netlink support)
4
+
3
5
  http://god.rubyforge.org
4
6
 
5
7
  == DESCRIPTION:
data/Rakefile CHANGED
@@ -2,9 +2,8 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require 'hoe'
5
- require './lib/god.rb'
6
5
 
7
- Hoe.new('god', God::VERSION) do |p|
6
+ Hoe.new('god', '0.2.0') do |p|
8
7
  p.rubyforge_name = 'god'
9
8
  p.author = 'Tom Preston-Werner'
10
9
  p.email = 'tom@rubyisawesome.com'
@@ -13,6 +12,7 @@ Hoe.new('god', God::VERSION) do |p|
13
12
  p.description = "God is an easy to configure, easy to extend monitoring framework written in Ruby."
14
13
  p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
15
14
  p.extra_deps << ['daemons', '>=1.0.7']
15
+ p.spec_extras = {:extensions => ['ext/god/extconf.rb']}
16
16
  end
17
17
 
18
18
  desc "Open an irb session preloaded with this library"
@@ -1,3 +1,5 @@
1
+ # run with: god start -c /path/to/gravatar.god
2
+ #
1
3
  # This is the actual config file used to keep the mongrels of
2
4
  # gravatar.com running.
3
5
 
@@ -8,8 +10,11 @@ God.meddle do |god|
8
10
  god.watch do |w|
9
11
  w.name = "gravatar2-mongrel-#{port}"
10
12
  w.interval = 30 # seconds
11
- w.start = "mongrel_rails cluster::start --only #{port} -c #{RAILS_ROOT}"
12
- w.stop = "mongrel_rails cluster::stop --only #{port} -c #{RAILS_ROOT}"
13
+ w.start = "mongrel_rails cluster::start --only #{port} \
14
+ -C #{RAILS_ROOT}/config/mongrel_cluster.yml"
15
+ w.stop = "mongrel_rails cluster::stop --only #{port} \
16
+ -C #{RAILS_ROOT}/config/mongrel_cluster.yml"
17
+ w.grace = 10 # seconds
13
18
 
14
19
  pid_file = File.join(RAILS_ROOT, "log/mongrel.#{port}.pid")
15
20
 
@@ -19,6 +24,7 @@ God.meddle do |god|
19
24
 
20
25
  w.start_if do |start|
21
26
  start.condition(:process_not_running) do |c|
27
+ c.interval = 5 # seconds
22
28
  c.pid_file = pid_file
23
29
  end
24
30
  end
data/examples/local.god CHANGED
@@ -2,15 +2,14 @@
2
2
  # and running on your Mac.
3
3
 
4
4
  # Run with:
5
- # god local.god
5
+ # god start -c /path/to/local.god
6
6
 
7
7
  RAILS_ROOT = "/Users/tom/dev/powerset/querytopia"
8
8
 
9
9
  God.meddle do |god|
10
- god.interval = 5 # seconds
11
-
12
10
  god.watch do |w|
13
11
  w.name = "local-3000"
12
+ w.interval = 5 # seconds
14
13
  w.start = "mongrel_rails start -P ./log/mongrel.pid -c #{RAILS_ROOT} -d"
15
14
  w.stop = "mongrel_rails stop -P ./log/mongrel.pid -c #{RAILS_ROOT}"
16
15
  w.grace = 5
@@ -24,7 +23,7 @@ God.meddle do |god|
24
23
 
25
24
  # start if process is not running
26
25
  w.start_if do |start|
27
- start.condition(:process_not_running) do |c|
26
+ start.condition(:process_exits) do |c|
28
27
  c.pid_file = pid_file
29
28
  end
30
29
  end
@@ -48,6 +47,7 @@ God.meddle do |god|
48
47
  # clear old session files
49
48
  god.watch do |w|
50
49
  w.name = "local-session-cleanup"
50
+ w.interval = 60 # seconds
51
51
  w.cwd = File.join(RAILS_ROOT, 'tmp/sessions')
52
52
  w.start = lambda do
53
53
  Dir['ruby_sess.*'].select { |f| File.mtime(f) < Time.now - (7 * 24 * 60 * 60) }.each { |f| File.delete(f) }
data/ext/god/Makefile ADDED
@@ -0,0 +1,149 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = .
7
+ topdir = /usr/local/lib/ruby/1.8/i686-darwin8.9.1
8
+ hdrdir = $(topdir)
9
+ VPATH = $(srcdir):$(topdir):$(hdrdir)
10
+ prefix = $(DESTDIR)/usr/local
11
+ exec_prefix = $(prefix)
12
+ sitedir = $(DESTDIR)/p/libdata/ruby
13
+ rubylibdir = $(libdir)/ruby/$(ruby_version)
14
+ docdir = $(datarootdir)/doc/$(PACKAGE)
15
+ dvidir = $(docdir)
16
+ datarootdir = $(prefix)/share
17
+ archdir = $(rubylibdir)/$(arch)
18
+ sbindir = $(exec_prefix)/sbin
19
+ psdir = $(docdir)
20
+ localedir = $(datarootdir)/locale
21
+ htmldir = $(docdir)
22
+ datadir = $(datarootdir)
23
+ includedir = $(prefix)/include
24
+ infodir = $(datarootdir)/info
25
+ sysconfdir = $(prefix)/etc
26
+ mandir = $(datarootdir)/man
27
+ libdir = $(exec_prefix)/lib
28
+ sharedstatedir = $(prefix)/com
29
+ oldincludedir = $(DESTDIR)/usr/include
30
+ pdfdir = $(docdir)
31
+ sitearchdir = $(sitelibdir)/$(sitearch)
32
+ bindir = $(exec_prefix)/bin
33
+ localstatedir = $(prefix)/var
34
+ sitelibdir = $(sitedir)/$(ruby_version)
35
+ libexecdir = $(exec_prefix)/libexec
36
+
37
+ CC = gcc
38
+ LIBRUBY = $(LIBRUBY_A)
39
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
40
+ LIBRUBYARG_SHARED =
41
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
42
+
43
+ RUBY_EXTCONF_H =
44
+ CFLAGS = -fno-common -g -O2 -pipe -fno-common
45
+ INCFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir)
46
+ CPPFLAGS =
47
+ CXXFLAGS = $(CFLAGS)
48
+ DLDFLAGS =
49
+ LDSHARED = cc -dynamic -bundle -undefined suppress -flat_namespace
50
+ AR = ar
51
+ EXEEXT =
52
+
53
+ RUBY_INSTALL_NAME = ruby
54
+ RUBY_SO_NAME = ruby
55
+ arch = i686-darwin8.9.1
56
+ sitearch = i686-darwin8.9.1
57
+ ruby_version = 1.8
58
+ ruby = /usr/local/bin/ruby
59
+ RUBY = $(ruby)
60
+ RM = rm -f
61
+ MAKEDIRS = mkdir -p
62
+ INSTALL = /usr/bin/install -c
63
+ INSTALL_PROG = $(INSTALL) -m 0755
64
+ INSTALL_DATA = $(INSTALL) -m 644
65
+ COPY = cp
66
+
67
+ #### End of system configuration section. ####
68
+
69
+ preload =
70
+
71
+ libpath = $(libdir)
72
+ LIBPATH = -L"$(libdir)"
73
+ DEFFILE =
74
+
75
+ CLEANFILES =
76
+ DISTCLEANFILES =
77
+
78
+ extout =
79
+ extout_prefix =
80
+ target_prefix =
81
+ LOCAL_LIBS =
82
+ LIBS = -lpthread -ldl -lobjc
83
+ SRCS = kqueue_handler.c netlink_handler.c
84
+ OBJS = kqueue_handler.o netlink_handler.o
85
+ TARGET = kqueue_handler_ext
86
+ DLLIB = $(TARGET).bundle
87
+ EXTSTATIC =
88
+ STATIC_LIB =
89
+
90
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
91
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
92
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
93
+
94
+ TARGET_SO = $(DLLIB)
95
+ CLEANLIBS = $(TARGET).bundle $(TARGET).il? $(TARGET).tds $(TARGET).map
96
+ CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
97
+
98
+ all: $(DLLIB)
99
+ static: $(STATIC_LIB)
100
+
101
+ clean:
102
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
103
+
104
+ distclean: clean
105
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
106
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
107
+
108
+ realclean: distclean
109
+ install: install-so install-rb
110
+
111
+ install-so: $(RUBYARCHDIR)
112
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
113
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
114
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
115
+ install-rb: pre-install-rb install-rb-default
116
+ install-rb-default: pre-install-rb-default
117
+ pre-install-rb: Makefile
118
+ pre-install-rb-default: Makefile
119
+ $(RUBYARCHDIR):
120
+ $(MAKEDIRS) $@
121
+
122
+ site-install: site-install-so site-install-rb
123
+ site-install-so: install-so
124
+ site-install-rb: install-rb
125
+
126
+ .SUFFIXES: .c .m .cc .cxx .cpp .C .o
127
+
128
+ .cc.o:
129
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
130
+
131
+ .cxx.o:
132
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
133
+
134
+ .cpp.o:
135
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
136
+
137
+ .C.o:
138
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
139
+
140
+ .c.o:
141
+ $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
142
+
143
+ $(DLLIB): $(OBJS)
144
+ @-$(RM) $@
145
+ $(LDSHARED) $(DLDFLAGS) $(LIBPATH) -o $@ $(OBJS) $(LOCAL_LIBS) $(LIBS)
146
+
147
+
148
+
149
+ $(OBJS): ruby.h defines.h
@@ -0,0 +1,8 @@
1
+ require 'mkmf'
2
+
3
+ case RUBY_PLATFORM
4
+ when /bsd/i, /darwin/i
5
+ create_makefile 'kqueue_handler_ext'
6
+ when /linux/i
7
+ create_makefile 'netlink_handler_ext'
8
+ end
@@ -0,0 +1,122 @@
1
+ #if defined(__FreeBSD__) || defined(__APPLE__)
2
+
3
+ #include <ruby.h>
4
+ #include <sys/event.h>
5
+ #include <sys/time.h>
6
+ #include <errno.h>
7
+
8
+ static VALUE cKQueueHandler;
9
+ static VALUE cEventHandler;
10
+ static VALUE mGod;
11
+
12
+ static ID proc_exit;
13
+ static ID proc_fork;
14
+ static ID m_call;
15
+ static ID m_size;
16
+ static ID m_deregister;
17
+
18
+ static int kq;
19
+ int num_events;
20
+
21
+ #define NUM_EVENTS FIX2INT(rb_funcall(rb_cv_get(cEventHandler, "@@actions"), m_size, 0))
22
+
23
+ VALUE
24
+ kqh_event_mask(VALUE klass, VALUE sym)
25
+ {
26
+ ID id = SYM2ID(sym);
27
+ if (proc_exit == id) {
28
+ return UINT2NUM(NOTE_EXIT);
29
+ } else if (proc_fork == id) {
30
+ return UINT2NUM(NOTE_FORK);
31
+ } else {
32
+ rb_raise(rb_eNotImpError, "Event `%s` not implemented", rb_id2name(id));
33
+ }
34
+
35
+ return Qnil;
36
+ }
37
+
38
+
39
+ VALUE
40
+ kqh_monitor_process(VALUE klass, VALUE pid, VALUE mask)
41
+ {
42
+ struct kevent new_event;
43
+ ID event;
44
+
45
+ u_int fflags = NUM2UINT(mask);
46
+
47
+ EV_SET(&new_event, FIX2UINT(pid), EVFILT_PROC,
48
+ EV_ADD | EV_ENABLE, fflags, 0, 0);
49
+
50
+ if (-1 == kevent(kq, &new_event, 1, NULL, 0, NULL)) {
51
+ rb_raise(rb_eStandardError, strerror(errno));
52
+ }
53
+
54
+ num_events = NUM_EVENTS;
55
+
56
+ return Qnil;
57
+ }
58
+
59
+ VALUE
60
+ kqh_handle_events()
61
+ {
62
+ int nevents, i, num_to_fetch;
63
+ struct kevent *events;
64
+ fd_set read_set;
65
+
66
+ FD_ZERO(&read_set);
67
+ FD_SET(kq, &read_set);
68
+
69
+ // Don't actually run this method until we've got an event
70
+ rb_thread_select(kq + 1, &read_set, NULL, NULL, NULL);
71
+
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));
75
+
76
+ if (NULL == events) {
77
+ rb_raise(rb_eStandardError, strerror(errno));
78
+ }
79
+
80
+ nevents = kevent(kq, NULL, 0, events, num_to_fetch, NULL);
81
+
82
+ if (-1 == nevents) {
83
+ rb_raise(rb_eStandardError, strerror(errno));
84
+ } else {
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));
90
+ }
91
+ }
92
+ }
93
+
94
+ free(events);
95
+
96
+ return INT2FIX(nevents);
97
+ }
98
+
99
+ void
100
+ Init_kqueue_handler_ext()
101
+ {
102
+ kq = kqueue();
103
+
104
+ if (kq == -1) {
105
+ rb_raise(rb_eStandardError, "kqueue initilization failed");
106
+ }
107
+
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");
113
+
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);
120
+ }
121
+
122
+ #endif
@@ -0,0 +1,140 @@
1
+ #ifdef __linux__ /* only build on linux */
2
+
3
+ #include <ruby.h>
4
+ #include <sys/types.h>
5
+ #include <sys/socket.h>
6
+ #include <linux/netlink.h>
7
+ #include <linux/connector.h>
8
+ #include <linux/cn_proc.h>
9
+ #include <errno.h>
10
+
11
+ static VALUE cNetlinkHandler;
12
+ static VALUE cEventHandler;
13
+ static VALUE mGod;
14
+
15
+ static ID proc_exit;
16
+ static ID proc_fork;
17
+ static ID m_call;
18
+ static ID m_watching_pid;
19
+
20
+ static int nl_sock; /* socket for netlink connection */
21
+
22
+
23
+ VALUE
24
+ nlh_handle_events()
25
+ {
26
+ char buff[CONNECTOR_MAX_MSG_SIZE];
27
+ struct nlmsghdr *hdr;
28
+ struct proc_event *event;
29
+
30
+ fd_set fds;
31
+
32
+ FD_ZERO(&fds);
33
+ FD_SET(nl_sock, &fds);
34
+
35
+ if (0 > rb_thread_select(nl_sock + 1, &fds, NULL, NULL, NULL)) {
36
+ rb_raise(rb_eStandardError, strerror(errno));
37
+ }
38
+
39
+ /* If there were no events detected, return */
40
+ if (! FD_ISSET(nl_sock, &fds)) {
41
+ return INT2FIX(0);
42
+ }
43
+
44
+ /* if there are events, make calls */
45
+ if (-1 == recv(nl_sock, buff, sizeof(buff), 0)) {
46
+ rb_raise(rb_eStandardError, strerror(errno));
47
+ }
48
+
49
+ hdr = (struct nlmsghdr *)buff;
50
+
51
+ if (NLMSG_ERROR == hdr->nlmsg_type) {
52
+ rb_raise(rb_eStandardError, strerror(errno));
53
+ } else if (NLMSG_DONE == hdr->nlmsg_type) {
54
+
55
+ event = (struct proc_event *)((struct cn_msg *)NLMSG_DATA(hdr))->data;
56
+
57
+ switch(event->what) {
58
+ case PROC_EVENT_EXIT:
59
+ if (Qnil == rb_funcall(cEventHandler, m_watching_pid, 1, INT2FIX(event->event_data.exit.process_pid))) {
60
+ return INT2FIX(0);
61
+ }
62
+
63
+ rb_funcall(cEventHandler, m_call, 2, INT2FIX(event->event_data.exit.process_pid), ID2SYM(proc_exit));
64
+ return INT2FIX(1);
65
+
66
+ /* TODO: On fork, call and pass pid of child */
67
+ case PROC_EVENT_FORK:
68
+ if (Qnil == rb_funcall(cEventHandler, m_watching_pid, 1, INT2FIX(event->event_data.fork.parent_pid))) {
69
+ return INT2FIX(0);
70
+ }
71
+
72
+ rb_funcall(cEventHandler, m_call, 2, INT2FIX(event->event_data.fork.parent_pid), ID2SYM(proc_fork));
73
+ return INT2FIX(1);
74
+ }
75
+ }
76
+
77
+ return Qnil;
78
+ }
79
+
80
+
81
+ #define NL_MESSAGE_SIZE (sizeof(struct nlmsghdr) + sizeof(struct cn_msg) + \
82
+ sizeof(int))
83
+
84
+ void
85
+ connect_to_netlink()
86
+ {
87
+ struct sockaddr_nl sa_nl; /* netlink interface info */
88
+ char buff[NL_MESSAGE_SIZE];
89
+ struct nlmsghdr *hdr; /* for telling netlink what we want */
90
+ struct cn_msg *msg; /* the actual connector message
91
+
92
+ /* connect to netlink socket */
93
+ nl_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
94
+
95
+ bzero(&sa_nl, sizeof(sa_nl));
96
+ sa_nl.nl_family = AF_NETLINK;
97
+ sa_nl.nl_groups = CN_IDX_PROC;
98
+ sa_nl.nl_pid = getpid();
99
+
100
+ bind(nl_sock, (struct sockaddr *)&sa_nl, sizeof(sa_nl));
101
+
102
+ /* Fill header */
103
+ hdr = (struct nlmsghdr *)buff;
104
+ hdr->nlmsg_len = NL_MESSAGE_SIZE;
105
+ hdr->nlmsg_type = NLMSG_DONE;
106
+ hdr->nlmsg_flags = 0;
107
+ hdr->nlmsg_seq = 0;
108
+ hdr->nlmsg_pid = getpid();
109
+
110
+ /* Fill message */
111
+ msg = (struct cn_msg *)NLMSG_DATA(hdr);
112
+ msg->id.idx = CN_IDX_PROC; /* Connecting to process information */
113
+ msg->id.val = CN_VAL_PROC;
114
+ msg->seq = 0;
115
+ msg->ack = 0;
116
+ msg->len = sizeof(int);
117
+ msg->data[0] = PROC_CN_MCAST_LISTEN;
118
+
119
+ if (-1 == send(nl_sock, hdr, hdr->nlmsg_len, 0)) {
120
+ rb_raise(rb_eStandardError, strerror(errno));
121
+ }
122
+ }
123
+
124
+ void
125
+ Init_netlink_handler_ext()
126
+ {
127
+ proc_exit = rb_intern("proc_exit");
128
+ proc_fork = rb_intern("proc_fork");
129
+ m_call = rb_intern("call");
130
+ m_watching_pid = rb_intern("watching_pid?");
131
+
132
+ mGod = rb_const_get(rb_cObject, rb_intern("God"));
133
+ cEventHandler = rb_const_get(mGod, rb_intern("EventHandler"));
134
+ cNetlinkHandler = rb_define_class_under(mGod, "NetlinkHandler", rb_cObject);
135
+ rb_define_singleton_method(cNetlinkHandler, "handle_events", nlh_handle_events, 0);
136
+
137
+ connect_to_netlink();
138
+ }
139
+
140
+ #endif