god 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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