firenxis-god 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. data/Announce.txt +135 -0
  2. data/History.txt +393 -0
  3. data/README.txt +59 -0
  4. data/Rakefile +142 -0
  5. data/bin/god +132 -0
  6. data/ext/god/.gitignore +5 -0
  7. data/ext/god/extconf.rb +55 -0
  8. data/ext/god/kqueue_handler.c +125 -0
  9. data/ext/god/netlink_handler.c +168 -0
  10. data/god.gemspec +164 -0
  11. data/lib/god.rb +701 -0
  12. data/lib/god/behavior.rb +52 -0
  13. data/lib/god/behaviors/clean_pid_file.rb +21 -0
  14. data/lib/god/behaviors/clean_unix_socket.rb +21 -0
  15. data/lib/god/behaviors/notify_when_flapping.rb +51 -0
  16. data/lib/god/cli/command.rb +256 -0
  17. data/lib/god/cli/run.rb +172 -0
  18. data/lib/god/cli/version.rb +23 -0
  19. data/lib/god/compat19.rb +36 -0
  20. data/lib/god/condition.rb +96 -0
  21. data/lib/god/conditions/always.rb +23 -0
  22. data/lib/god/conditions/complex.rb +86 -0
  23. data/lib/god/conditions/cpu_usage.rb +80 -0
  24. data/lib/god/conditions/degrading_lambda.rb +52 -0
  25. data/lib/god/conditions/disk_usage.rb +32 -0
  26. data/lib/god/conditions/file_mtime.rb +28 -0
  27. data/lib/god/conditions/flapping.rb +128 -0
  28. data/lib/god/conditions/http_response_code.rb +168 -0
  29. data/lib/god/conditions/lambda.rb +25 -0
  30. data/lib/god/conditions/memory_usage.rb +82 -0
  31. data/lib/god/conditions/process_exits.rb +72 -0
  32. data/lib/god/conditions/process_running.rb +74 -0
  33. data/lib/god/conditions/tries.rb +44 -0
  34. data/lib/god/configurable.rb +57 -0
  35. data/lib/god/contact.rb +114 -0
  36. data/lib/god/contacts/campfire.rb +121 -0
  37. data/lib/god/contacts/email.rb +136 -0
  38. data/lib/god/contacts/jabber.rb +75 -0
  39. data/lib/god/contacts/prowl.rb +57 -0
  40. data/lib/god/contacts/scout.rb +55 -0
  41. data/lib/god/contacts/twitter.rb +51 -0
  42. data/lib/god/contacts/webhook.rb +73 -0
  43. data/lib/god/dependency_graph.rb +41 -0
  44. data/lib/god/diagnostics.rb +37 -0
  45. data/lib/god/driver.rb +206 -0
  46. data/lib/god/errors.rb +24 -0
  47. data/lib/god/event_handler.rb +108 -0
  48. data/lib/god/event_handlers/dummy_handler.rb +13 -0
  49. data/lib/god/event_handlers/kqueue_handler.rb +17 -0
  50. data/lib/god/event_handlers/netlink_handler.rb +13 -0
  51. data/lib/god/logger.rb +109 -0
  52. data/lib/god/metric.rb +59 -0
  53. data/lib/god/process.rb +363 -0
  54. data/lib/god/registry.rb +32 -0
  55. data/lib/god/simple_logger.rb +59 -0
  56. data/lib/god/socket.rb +107 -0
  57. data/lib/god/sugar.rb +47 -0
  58. data/lib/god/sys_logger.rb +45 -0
  59. data/lib/god/system/portable_poller.rb +42 -0
  60. data/lib/god/system/process.rb +50 -0
  61. data/lib/god/system/slash_proc_poller.rb +92 -0
  62. data/lib/god/task.rb +503 -0
  63. data/lib/god/timeline.rb +25 -0
  64. data/lib/god/trigger.rb +43 -0
  65. data/lib/god/watch.rb +188 -0
  66. data/test/configs/child_events/child_events.god +44 -0
  67. data/test/configs/child_events/simple_server.rb +3 -0
  68. data/test/configs/child_polls/child_polls.god +37 -0
  69. data/test/configs/child_polls/simple_server.rb +12 -0
  70. data/test/configs/complex/complex.god +59 -0
  71. data/test/configs/complex/simple_server.rb +3 -0
  72. data/test/configs/contact/contact.god +108 -0
  73. data/test/configs/contact/simple_server.rb +3 -0
  74. data/test/configs/daemon_events/daemon_events.god +37 -0
  75. data/test/configs/daemon_events/simple_server.rb +8 -0
  76. data/test/configs/daemon_events/simple_server_stop.rb +11 -0
  77. data/test/configs/daemon_polls/daemon_polls.god +17 -0
  78. data/test/configs/daemon_polls/simple_server.rb +6 -0
  79. data/test/configs/degrading_lambda/degrading_lambda.god +31 -0
  80. data/test/configs/degrading_lambda/tcp_server.rb +15 -0
  81. data/test/configs/lifecycle/lifecycle.god +25 -0
  82. data/test/configs/matias/matias.god +50 -0
  83. data/test/configs/real.rb +59 -0
  84. data/test/configs/running_load/running_load.god +16 -0
  85. data/test/configs/stop_options/simple_server.rb +12 -0
  86. data/test/configs/stop_options/stop_options.god +39 -0
  87. data/test/configs/stress/simple_server.rb +3 -0
  88. data/test/configs/stress/stress.god +15 -0
  89. data/test/configs/task/logs/.placeholder +0 -0
  90. data/test/configs/task/task.god +26 -0
  91. data/test/configs/test.rb +61 -0
  92. data/test/helper.rb +141 -0
  93. data/test/suite.rb +6 -0
  94. data/test/test_behavior.rb +18 -0
  95. data/test/test_campfire.rb +23 -0
  96. data/test/test_condition.rb +50 -0
  97. data/test/test_conditions_disk_usage.rb +50 -0
  98. data/test/test_conditions_http_response_code.rb +109 -0
  99. data/test/test_conditions_process_running.rb +40 -0
  100. data/test/test_conditions_tries.rb +67 -0
  101. data/test/test_contact.rb +109 -0
  102. data/test/test_dependency_graph.rb +62 -0
  103. data/test/test_driver.rb +11 -0
  104. data/test/test_email.rb +34 -0
  105. data/test/test_event_handler.rb +80 -0
  106. data/test/test_god.rb +570 -0
  107. data/test/test_handlers_kqueue_handler.rb +16 -0
  108. data/test/test_jabber.rb +29 -0
  109. data/test/test_logger.rb +55 -0
  110. data/test/test_metric.rb +72 -0
  111. data/test/test_process.rb +247 -0
  112. data/test/test_prowl.rb +15 -0
  113. data/test/test_registry.rb +15 -0
  114. data/test/test_socket.rb +34 -0
  115. data/test/test_sugar.rb +42 -0
  116. data/test/test_system_portable_poller.rb +17 -0
  117. data/test/test_system_process.rb +30 -0
  118. data/test/test_task.rb +246 -0
  119. data/test/test_timeline.rb +37 -0
  120. data/test/test_trigger.rb +59 -0
  121. data/test/test_watch.rb +279 -0
  122. data/test/test_webhook.rb +15 -0
  123. metadata +362 -0
data/README.txt ADDED
@@ -0,0 +1,59 @@
1
+ god
2
+ by Tom Preston-Werner
3
+ Kevin Clark (kqueue/netlink support)
4
+
5
+ http://god.rubyforge.org
6
+
7
+ == DESCRIPTION:
8
+
9
+ God is an easy to configure, easy to extend monitoring framework written
10
+ in Ruby.
11
+
12
+ Keeping your server processes and tasks running should be a simple part of
13
+ your deployment process. God aims to be the simplest, most powerful
14
+ monitoring application available.
15
+
16
+ == DOCUMENTATION:
17
+
18
+ See online documentation at http://god.rubyforge.org
19
+
20
+ == COMMUNITY:
21
+
22
+ Sign up for the god mailing list at http://groups.google.com/group/god-rb
23
+
24
+ == INSTALL:
25
+
26
+ $ sudo gem install god
27
+
28
+ == CONTRIBUTE:
29
+
30
+ Latest code is available at http://github.com/mojombo/god
31
+
32
+ The 'master' branch can be cloned with:
33
+
34
+ $ git clone git://github.com/mojombo/god.git
35
+
36
+ == LICENSE:
37
+
38
+ (The MIT License)
39
+
40
+ Copyright (c) 2007 Tom Preston-Werner
41
+
42
+ Permission is hereby granted, free of charge, to any person obtaining
43
+ a copy of this software and associated documentation files (the
44
+ 'Software'), to deal in the Software without restriction, including
45
+ without limitation the rights to use, copy, modify, merge, publish,
46
+ distribute, sublicense, and/or sell copies of the Software, and to
47
+ permit persons to whom the Software is furnished to do so, subject to
48
+ the following conditions:
49
+
50
+ The above copyright notice and this permission notice shall be
51
+ included in all copies or substantial portions of the Software.
52
+
53
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
54
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
55
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
56
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
57
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
58
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
59
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,142 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'date'
4
+
5
+ #############################################################################
6
+ #
7
+ # The name of the package
8
+ #
9
+ #############################################################################
10
+
11
+ NAME = 'god'
12
+
13
+ #############################################################################
14
+ #
15
+ # Helper functions
16
+ #
17
+ #############################################################################
18
+
19
+ def source_version
20
+ line = File.read("lib/#{NAME}.rb")[/^\s*VERSION\s*=\s*.*/]
21
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
22
+ end
23
+
24
+ def gemspec_file
25
+ "#{NAME}.gemspec"
26
+ end
27
+
28
+ def gem_file
29
+ "#{NAME}-#{source_version}.gem"
30
+ end
31
+
32
+ #############################################################################
33
+ #
34
+ # Standard tasks
35
+ #
36
+ #############################################################################
37
+
38
+ task :default => :test
39
+
40
+ require 'rake/testtask'
41
+ Rake::TestTask.new(:test) do |test|
42
+ test.libs << 'lib' << 'test'
43
+ test.pattern = 'test/**/test_*.rb'
44
+ test.verbose = true
45
+ end
46
+
47
+ desc "Generate and open coverage stats via rcov"
48
+ task :coverage do
49
+ require 'rcov'
50
+ sh "rm -fr coverage"
51
+ sh "rcov test/test_*.rb"
52
+ sh "open coverage/index.html"
53
+ end
54
+
55
+ require 'rake/rdoctask'
56
+ Rake::RDocTask.new do |rdoc|
57
+ rdoc.rdoc_dir = 'rdoc'
58
+ rdoc.title = "#{NAME} #{source_version}"
59
+ rdoc.rdoc_files.include('README*')
60
+ rdoc.rdoc_files.include('lib/**/*.rb')
61
+ end
62
+
63
+ desc "Open an irb session preloaded with this library"
64
+ task :console do
65
+ sh "irb -rubygems -r ./lib/#{NAME}.rb"
66
+ end
67
+
68
+ #############################################################################
69
+ #
70
+ # Custom tasks (add your own tasks here)
71
+ #
72
+ #############################################################################
73
+
74
+ desc "Upload site to Rubyforge"
75
+ task :site do
76
+ sh "scp -r site/* mojombo@god.rubyforge.org:/var/www/gforge-projects/god"
77
+ end
78
+
79
+ desc "Upload site to Rubyforge"
80
+ task :site_edge do
81
+ sh "scp -r site/* mojombo@god.rubyforge.org:/var/www/gforge-projects/god/edge"
82
+ end
83
+
84
+ #############################################################################
85
+ #
86
+ # Packaging tasks
87
+ #
88
+ #############################################################################
89
+
90
+ task :release => :build do
91
+ unless `git branch` =~ /^\* master$/
92
+ puts "You must be on the master branch to release!"
93
+ exit!
94
+ end
95
+ sh "git commit --allow-empty -a -m 'up to #{source_version}'"
96
+ sh "git tag v#{source_version}"
97
+ sh "git push origin master --tags"
98
+ sh "gem push pkg/#{NAME}-#{source_version}.gem"
99
+ end
100
+
101
+ task :build => :gemspec do
102
+ sh "mkdir -p pkg"
103
+ sh "gem build #{gemspec_file}"
104
+ sh "mv #{gem_file} pkg"
105
+ end
106
+
107
+ task :gemspec => :validate do
108
+ # read spec file and split out manifest section
109
+ spec = File.read(gemspec_file)
110
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
111
+
112
+ # replace version and date
113
+ head.sub!(/\.version = '.*'/, ".version = '#{source_version}'")
114
+ head.sub!(/\.date = '.*'/, ".date = '#{Date.today.to_s}'")
115
+
116
+ # determine file list from git ls-files
117
+ files = `git ls-files`.
118
+ split("\n").
119
+ sort.
120
+ reject { |file| file =~ /^\./ }.
121
+ reject { |file| file =~ /^(examples|ideas|init|site)/ }.
122
+ map { |file| " #{file}" }.
123
+ join("\n")
124
+
125
+ # piece file back together and write
126
+ manifest = " s.files = %w[\n#{files}\n ]\n"
127
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
128
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
129
+ puts "Updated #{gemspec_file}"
130
+ end
131
+
132
+ task :validate do
133
+ libfiles = Dir['lib/*'] - ["lib/#{NAME}.rb", "lib/#{NAME}"]
134
+ unless libfiles.empty?
135
+ puts "Directory `lib` should only contain a `#{NAME}.rb` file and `#{NAME}` dir."
136
+ exit!
137
+ end
138
+ unless Dir['VERSION*'].empty?
139
+ puts "A `VERSION` file at root level violates Gem best practices."
140
+ exit!
141
+ end
142
+ end
data/bin/god ADDED
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ STDOUT.sync = true
4
+
5
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
6
+
7
+ require 'rubygems'
8
+ require 'optparse'
9
+ require 'drb'
10
+ require 'yaml'
11
+
12
+ begin
13
+ # Save ARGV in case someone wants to use it later
14
+ ORIGINAL_ARGV = ARGV.dup
15
+
16
+ options = {:daemonize => true, :port => 17165, :syslog => true, :events => true}
17
+
18
+ opts = OptionParser.new do |opts|
19
+ opts.banner = <<-EOF
20
+ Usage:
21
+ Starting:
22
+ god [-c <config file>] [-p <port> | -b] [-P <file>] [-l <file>] [-D]
23
+
24
+ Querying:
25
+ god <command> <argument> [-p <port>]
26
+ god <command> [-p <port>]
27
+ god -v
28
+ god -V (must be run as root to be accurate on Linux)
29
+
30
+ Commands:
31
+ start <task or group name> start task or group
32
+ restart <task or group name> restart task or group
33
+ stop <task or group name> stop task or group
34
+ monitor <task or group name> monitor task or group
35
+ unmonitor <task or group name> unmonitor task or group
36
+ remove <task or group name> remove task or group from god
37
+ load <file> load a config into a running god
38
+ log <task name> show realtime log for given task
39
+ status [task or group name] show status
40
+ signal <task or group name> <sig> signal all matching tasks
41
+ quit stop god
42
+ terminate stop god and all tasks
43
+ check run self diagnostic
44
+
45
+ Options:
46
+ EOF
47
+
48
+ opts.on("-cCONFIG", "--config-file CONFIG", "Configuration file") do |x|
49
+ options[:config] = x
50
+ end
51
+
52
+ opts.on("-pPORT", "--port PORT", "Communications port (default 17165)") do |x|
53
+ options[:port] = x
54
+ end
55
+
56
+ opts.on("-b", "--auto-bind", "Auto-bind to an unused port number") do
57
+ options[:port] = "0"
58
+ end
59
+
60
+ opts.on("-PFILE", "--pid FILE", "Where to write the PID file") do |x|
61
+ options[:pid] = x
62
+ end
63
+
64
+ opts.on("-lFILE", "--log FILE", "Where to write the log file") do |x|
65
+ options[:log] = x
66
+ end
67
+
68
+ opts.on("-D", "--no-daemonize", "Don't daemonize") do
69
+ options[:daemonize] = false
70
+ end
71
+
72
+ opts.on("-v", "--version", "Print the version number and exit") do
73
+ options[:version] = true
74
+ end
75
+
76
+ opts.on("-V", "Print extended version and build information") do
77
+ options[:info] = true
78
+ end
79
+
80
+ opts.on("--log-level LEVEL", "Log level [debug|info|warn|error|fatal]") do |x|
81
+ options[:log_level] = x.to_sym
82
+ end
83
+
84
+ opts.on("--no-syslog", "Disable output to syslog") do
85
+ options[:syslog] = false
86
+ end
87
+
88
+ opts.on("--attach PID", "Quit god when the attached process dies") do |x|
89
+ options[:attach] = x
90
+ end
91
+
92
+ opts.on("--no-events", "Disable the event system") do
93
+ options[:events] = false
94
+ end
95
+
96
+ opts.on("--bleakhouse", "Enable bleakhouse profiling") do
97
+ options[:bleakhouse] = true
98
+ end
99
+ end
100
+
101
+ opts.parse!
102
+
103
+ # validate
104
+ if options[:log_level] && ![:debug, :info, :warn, :error, :fatal].include?(options[:log_level])
105
+ abort("Invalid log level '#{options[:log_level]}'")
106
+ end
107
+
108
+ # dispatch
109
+ if !options[:config] && options[:version]
110
+ require 'god'
111
+ God::CLI::Version.version
112
+ elsif !options[:config] && options[:info]
113
+ require 'god'
114
+ God::EventHandler.load
115
+ God::CLI::Version.version_extended
116
+ elsif !options[:config] && command = ARGV[0]
117
+ require 'god'
118
+ God::EventHandler.load
119
+ God::CLI::Command.new(command, options, ARGV)
120
+ else
121
+ require 'god/cli/run'
122
+ God::CLI::Run.new(options)
123
+ end
124
+ rescue Exception => e
125
+ if e.instance_of?(SystemExit)
126
+ raise
127
+ else
128
+ puts 'Uncaught exception'
129
+ puts e.message
130
+ puts e.backtrace.join("\n")
131
+ end
132
+ end
@@ -0,0 +1,5 @@
1
+ Makefile
2
+ kqueue_handler_ext.bundle
3
+ kqueue_handler.o
4
+ netlink_handler_ext.bundle
5
+ netlink_handler.o
@@ -0,0 +1,55 @@
1
+ require 'mkmf'
2
+
3
+ fail = false
4
+
5
+ def create_dummy_makefile
6
+ File.open("Makefile", 'w') do |f|
7
+ f.puts "all:"
8
+ f.puts "install:"
9
+ end
10
+ end
11
+
12
+ case RUBY_PLATFORM
13
+ when /bsd/i, /darwin/i
14
+ unless have_header('sys/event.h')
15
+ puts
16
+ puts "Missing 'sys/event.h' header"
17
+ fail = true
18
+ end
19
+
20
+ if fail
21
+ puts
22
+ puts "Events handler could not be compiled (see above error). Your god installation will not support event conditions."
23
+ create_dummy_makefile
24
+ else
25
+ create_makefile 'kqueue_handler_ext'
26
+ end
27
+ when /linux/i
28
+ unless have_header('linux/netlink.h')
29
+ puts
30
+ puts "Missing 'linux/netlink.h' header(s)"
31
+ puts "You may need to install a header package for your system"
32
+ fail = true
33
+ end
34
+
35
+ unless have_header('linux/connector.h') && have_header('linux/cn_proc.h')
36
+ puts
37
+ puts "Missing 'linux/connector.h', or 'linux/cn_proc.h' header(s)"
38
+ puts "These are only available in Linux kernel 2.6.15 and later (run `uname -a` to find yours)"
39
+ puts "You may need to install a header package for your system"
40
+ fail = true
41
+ end
42
+
43
+ if fail
44
+ puts
45
+ puts "Events handler could not be compiled (see above error). Your god installation will not support event conditions."
46
+ create_dummy_makefile
47
+ else
48
+ create_makefile 'netlink_handler_ext'
49
+ end
50
+ else
51
+ puts
52
+ puts "Unsupported platform '#{RUBY_PLATFORM}'. Supported platforms are BSD, DARWIN, and LINUX."
53
+ puts "Your god installation will not support event conditions."
54
+ create_dummy_makefile
55
+ end
@@ -0,0 +1,125 @@
1
+ #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__)
2
+
3
+ #include <ruby.h>
4
+ #include <sys/event.h>
5
+ #include <sys/time.h>
6
+ #include <errno.h>
7
+
8
+ static VALUE mGod;
9
+ static VALUE cKQueueHandler;
10
+ static VALUE cEventHandler;
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
+ (void)event; //!< Silence warning about unused var, should be removed?
46
+
47
+ u_int fflags = NUM2UINT(mask);
48
+
49
+ EV_SET(&new_event, FIX2UINT(pid), EVFILT_PROC,
50
+ EV_ADD | EV_ENABLE, fflags, 0, 0);
51
+
52
+ if (-1 == kevent(kq, &new_event, 1, NULL, 0, NULL)) {
53
+ rb_raise(rb_eStandardError, "%s", strerror(errno));
54
+ }
55
+
56
+ num_events = NUM_EVENTS;
57
+
58
+ return Qnil;
59
+ }
60
+
61
+ VALUE
62
+ kqh_handle_events()
63
+ {
64
+ int nevents, i, num_to_fetch;
65
+ struct kevent *events;
66
+ fd_set read_set;
67
+
68
+ FD_ZERO(&read_set);
69
+ FD_SET(kq, &read_set);
70
+
71
+ // Don't actually run this method until we've got an event
72
+ rb_thread_select(kq + 1, &read_set, NULL, NULL, NULL);
73
+
74
+ // Grabbing num_events once for thread safety
75
+ num_to_fetch = num_events;
76
+ events = (struct kevent*)malloc(num_to_fetch * sizeof(struct kevent));
77
+
78
+ if (NULL == events) {
79
+ rb_raise(rb_eStandardError, "%s", strerror(errno));
80
+ }
81
+
82
+ nevents = kevent(kq, NULL, 0, events, num_to_fetch, NULL);
83
+
84
+ if (-1 == nevents) {
85
+ free(events);
86
+ rb_raise(rb_eStandardError, "%s", strerror(errno));
87
+ } else {
88
+ for (i = 0; i < nevents; i++) {
89
+ if (events[i].fflags & NOTE_EXIT) {
90
+ rb_funcall(cEventHandler, m_call, 2, INT2NUM(events[i].ident), ID2SYM(proc_exit));
91
+ } else if (events[i].fflags & NOTE_FORK) {
92
+ rb_funcall(cEventHandler, m_call, 2, INT2NUM(events[i].ident), ID2SYM(proc_fork));
93
+ }
94
+ }
95
+ }
96
+
97
+ free(events);
98
+
99
+ return INT2FIX(nevents);
100
+ }
101
+
102
+ void
103
+ Init_kqueue_handler_ext()
104
+ {
105
+ kq = kqueue();
106
+
107
+ if (kq == -1) {
108
+ rb_raise(rb_eStandardError, "kqueue initilization failed");
109
+ }
110
+
111
+ proc_exit = rb_intern("proc_exit");
112
+ proc_fork = rb_intern("proc_fork");
113
+ m_call = rb_intern("call");
114
+ m_size = rb_intern("size");
115
+ m_deregister = rb_intern("deregister");
116
+
117
+ mGod = rb_const_get(rb_cObject, rb_intern("God"));
118
+ cEventHandler = rb_const_get(mGod, rb_intern("EventHandler"));
119
+ cKQueueHandler = rb_define_class_under(mGod, "KQueueHandler", rb_cObject);
120
+ rb_define_singleton_method(cKQueueHandler, "monitor_process", kqh_monitor_process, 2);
121
+ rb_define_singleton_method(cKQueueHandler, "handle_events", kqh_handle_events, 0);
122
+ rb_define_singleton_method(cKQueueHandler, "event_mask", kqh_event_mask, 1);
123
+ }
124
+
125
+ #endif