fire_and_forget 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/Gemfile.lock +0 -8
  2. data/README.rdoc +75 -14
  3. data/bin/fire_forget +45 -22
  4. data/examples/long_task +27 -16
  5. data/fire_and_forget.gemspec +41 -4
  6. data/lib/fire_and_forget/client.rb +1 -1
  7. data/lib/fire_and_forget/command/fire.rb +23 -4
  8. data/lib/fire_and_forget/command/get_pid.rb +20 -0
  9. data/lib/fire_and_forget/command/set_pid.rb +0 -2
  10. data/lib/fire_and_forget/command/set_status.rb +1 -1
  11. data/lib/fire_and_forget/command.rb +11 -0
  12. data/lib/fire_and_forget/config.rb +3 -8
  13. data/lib/fire_and_forget/daemon.rb +14 -23
  14. data/lib/fire_and_forget/errors.rb +8 -0
  15. data/lib/fire_and_forget/launcher.rb +69 -6
  16. data/lib/fire_and_forget/server.rb +5 -1
  17. data/lib/fire_and_forget/task_description.rb +11 -0
  18. data/lib/fire_and_forget/utilities.rb +4 -4
  19. data/lib/fire_and_forget/version.rb +1 -1
  20. data/lib/fire_and_forget.rb +6 -2
  21. data/test/test_fire_and_forget.rb +59 -26
  22. data/vendor/daemons-1.1.0/LICENSE +29 -0
  23. data/vendor/daemons-1.1.0/README +224 -0
  24. data/vendor/daemons-1.1.0/Rakefile +88 -0
  25. data/vendor/daemons-1.1.0/Releases +152 -0
  26. data/vendor/daemons-1.1.0/TODO +2 -0
  27. data/vendor/daemons-1.1.0/lib/daemons/application.rb +468 -0
  28. data/vendor/daemons-1.1.0/lib/daemons/application_group.rb +194 -0
  29. data/vendor/daemons-1.1.0/lib/daemons/change_privilege.rb +19 -0
  30. data/vendor/daemons-1.1.0/lib/daemons/cmdline.rb +124 -0
  31. data/vendor/daemons-1.1.0/lib/daemons/controller.rb +140 -0
  32. data/vendor/daemons-1.1.0/lib/daemons/daemonize.rb +271 -0
  33. data/vendor/daemons-1.1.0/lib/daemons/etc_extension.rb +12 -0
  34. data/vendor/daemons-1.1.0/lib/daemons/exceptions.rb +28 -0
  35. data/vendor/daemons-1.1.0/lib/daemons/monitor.rb +138 -0
  36. data/vendor/daemons-1.1.0/lib/daemons/pid.rb +109 -0
  37. data/vendor/daemons-1.1.0/lib/daemons/pidfile.rb +116 -0
  38. data/vendor/daemons-1.1.0/lib/daemons/pidmem.rb +19 -0
  39. data/vendor/daemons-1.1.0/lib/daemons.rb +288 -0
  40. data/vendor/daemons-1.1.0/setup.rb +1360 -0
  41. data/vendor/json-1.5.0/COPYING +58 -0
  42. data/vendor/json-1.5.0/GPL +340 -0
  43. data/vendor/json-1.5.0/README +356 -0
  44. data/vendor/json-1.5.0/README-json-jruby.markdown +33 -0
  45. data/vendor/json-1.5.0/Rakefile +397 -0
  46. data/vendor/json-1.5.0/TODO +1 -0
  47. data/vendor/json-1.5.0/VERSION +1 -0
  48. data/vendor/json-1.5.0/lib/json/add/core.rb +147 -0
  49. data/vendor/json-1.5.0/lib/json/add/rails.rb +8 -0
  50. data/vendor/json-1.5.0/lib/json/common.rb +419 -0
  51. data/vendor/json-1.5.0/lib/json/editor.rb +1369 -0
  52. data/vendor/json-1.5.0/lib/json/pure/generator.rb +441 -0
  53. data/vendor/json-1.5.0/lib/json/pure/parser.rb +320 -0
  54. data/vendor/json-1.5.0/lib/json/pure.rb +15 -0
  55. data/vendor/json-1.5.0/lib/json/version.rb +8 -0
  56. data/vendor/json-1.5.0/lib/json.rb +10 -0
  57. metadata +41 -4
  58. data/lib/fire_and_forget/task.rb +0 -11
@@ -0,0 +1,88 @@
1
+ require 'rubygems'
2
+ #Gem::manage_gems
3
+
4
+ require 'rake/gempackagetask'
5
+ #require 'rake/testtask'
6
+ require 'rake/packagetask'
7
+ require 'rake/rdoctask'
8
+
9
+ $LOAD_PATH << './lib'
10
+ require 'daemons'
11
+
12
+
13
+ PKG_NAME = "daemons"
14
+
15
+ PKG_FILES = FileList[
16
+ "Rakefile", "Releases", "TODO", "README", "LICENSE",
17
+ "setup.rb",
18
+ "lib/**/*.rb",
19
+ #"test/**/*",
20
+ "examples/**/*"
21
+ ]
22
+ #PKG_FILES.exclude(%r(^test/tmp/.+))
23
+ PKG_FILES.exclude(%r(\.pid$))
24
+ PKG_FILES.exclude(%r(\.log$))
25
+
26
+ spec = Gem::Specification.new do |s|
27
+ s.name = PKG_NAME
28
+ s.version = Daemons::VERSION
29
+ s.author = "Thomas Uehlinger"
30
+ s.email = "th.uehlinger@gmx.ch"
31
+ s.rubyforge_project = "daemons"
32
+ s.homepage = "http://daemons.rubyforge.org"
33
+ s.platform = Gem::Platform::RUBY
34
+ s.summary = "A toolkit to create and control daemons in different ways"
35
+ s.description = <<-EOF
36
+ Daemons provides an easy way to wrap existing ruby scripts (for example a self-written server)
37
+ to be run as a daemon and to be controlled by simple start/stop/restart commands.
38
+
39
+ You can also call blocks as daemons and control them from the parent or just daemonize the current
40
+ process.
41
+
42
+ Besides this basic functionality, daemons offers many advanced features like exception
43
+ backtracing and logging (in case your ruby script crashes) and monitoring and automatic
44
+ restarting of your processes if they crash.
45
+ EOF
46
+
47
+ #s.files = FileList["{test,lib}/**/*"].exclude("rdoc").to_a
48
+ s.files = PKG_FILES
49
+ s.require_path = "lib"
50
+ s.autorequire = "daemons"
51
+ s.has_rdoc = true
52
+ s.extra_rdoc_files = ["README", "Releases", "TODO"]
53
+ end
54
+
55
+ Rake::GemPackageTask.new(spec) do |pkg|
56
+ pkg.need_tar = true
57
+ end
58
+
59
+
60
+ #Rake::PackageTask.new("package") do |p|
61
+ # p.name = PKG_NAME
62
+ # p.version = Daemons::VERSION
63
+ # p.need_tar = true
64
+ # p.need_zip = true
65
+ # p.package_files = PKG_FILES
66
+ #end
67
+
68
+
69
+ task :default => [:package]
70
+
71
+ desc 'Show information about the gem.'
72
+ task :debug_gem do
73
+ puts spec.to_ruby
74
+ end
75
+
76
+ task :upload do
77
+ sh "scp -r html/* uehli@rubyforge.org:/var/www/gforge-projects/daemons"
78
+ end
79
+
80
+
81
+ desc "Create the RDOC html files"
82
+ rd = Rake::RDocTask.new("rdoc") { |rdoc|
83
+ rdoc.rdoc_dir = 'html'
84
+ rdoc.title = "Daemons"
85
+ rdoc.options << '--line-numbers' << '--inline-source' << '--main' << 'README'
86
+ rdoc.rdoc_files.include('README', 'TODO', 'Releases')
87
+ rdoc.rdoc_files.include('lib/**/*.rb')
88
+ }
@@ -0,0 +1,152 @@
1
+ = Daemons Release History
2
+
3
+ == Release 1.1.0: June 20, 2010
4
+
5
+ * Honour the options[:app_name] in Daemons.daemonize (thanks to Ryan Tecco).
6
+ * Included a new option :stop_proc to specify a proc that will be called when a
7
+ daemonized process receives a request to stop (thanks to Dave Dupre).
8
+ * Only delete the pidfile if the current pid is the original pid (ghazel).
9
+ * Start when restart but no application running (pcreux).
10
+ * Silently continue if there is no pidfile (ghazel).
11
+ * We now per default wait for processes to stop and
12
+ kill them automatically it if they do not stop within a given time
13
+ (force_kill_waittime). Use the option --no_wait to not wait for processes to
14
+ stop.
15
+ * Set log files mode to 0644 (mikehale).
16
+ * Set pid file permissions to 0644 (mikehale).
17
+ * Added ability to change process uid/gid (mikehale).
18
+ * Fix for: If you happen to start a daemon from a process that has open file
19
+ descriptors these will stay open. As it is daemonize.rb only closes ruby IO
20
+ objects (thanks to Han Holl).
21
+ * New reload command (SIGHUP) (thanks to Michael Schuerig).
22
+
23
+ == Release 1.0.10: March 21, 2008
24
+
25
+ * By default, we now delete stray pid-files (i.e. pid-files which result for
26
+ example from a killed daemon) automatically. This function can be deactivated
27
+ by passing :keep_pid_files => true as an option.
28
+ * All pid files of :multiple daemons new get deleted correctly upon exit of the
29
+ daemons (reported by Han Holl).
30
+ * Use the signal 'KILL' instead of 'TERM' on Windows platforms.
31
+ * Use exit! in trap('TERM') instead of exit when option :hard_exit is given
32
+ (thanks to Han Holl).
33
+ * Did some clarification on the exception log.
34
+
35
+ == Release 1.0.9: October 29, 2007
36
+
37
+ * fixed a severe bug in the new Pid.running? function: function returned true if
38
+ the process did not exist (thanks to Jeremy Lawler).
39
+
40
+ == Release 1.0.8: September 24, 2007
41
+
42
+ * new Pid.running? function. Checking whether a process exists by sending
43
+ signal '0' (thanks to Dru Nelson).
44
+
45
+ == Release 1.0.7: July 7, 2007
46
+
47
+ * Patch to fix wrong ARGV when using :exec (in def start_exec:
48
+ Kernel.exec(script(), *(@app_argv || []))) (thanks to Alex McGuire).
49
+
50
+ == Release 1.0.6: Mai 8, 2007
51
+
52
+ * New option to pass an ARGV-style array to run and run_proc (thanks to Marc Evans).
53
+ * Additional patches for '/var/log' (thanks to Marc Evans).
54
+
55
+ == Release 1.0.5: February 24, 2007
56
+
57
+ * Applied patch that makes daemons to use '/var/log' as logfile
58
+ directory if you use :dir_mode = :system (thanks to Han Holl).
59
+ * Daemons should now work with Ruby 1.9 (at least the basic features).
60
+
61
+ == Release 1.0.4: January 17, 2007
62
+
63
+ * Document the :log_output option (thanks to Andrew Kuklewicz).
64
+ * Set STDOUT.sync = true when redirecting to a logfile (thanks to Andrew Kuklewicz).
65
+ * Should now run also correctly when there is no working 'ps ax' on the system
66
+ (thanks to Daniel Kehoe).
67
+
68
+ == Release 1.0.3: November 1, 2006
69
+
70
+ * Set the app_name correctly also for the monitor process (thanks to Ilya Novoselov).
71
+
72
+ == Release 1.0.2: September 26, 2006
73
+
74
+ * Changed the 'ps -ax' call back to 'ps ax'.
75
+ * Fixed the documentation for the :normal :dir_mode.
76
+ * As a default for Daemons.run_proc, the pid file is now saved in the current directory.
77
+ * In :ontop mode for running a proc (this is equal to calling something like 'ruby ctrl_proc.rb run'),
78
+ the proc now runs directly in the calling script, not in a forked process anymore (thanks to Paul Butcher).
79
+ * Set $0 to app_name in the daemons (thanks to Ilya Novoselov).
80
+
81
+ == Release 1.0.1: August 30, 2006
82
+
83
+ * Fixed a regex for parsing the 'ps ax' system call. (thanks to Garance Alistair Drosehn)
84
+
85
+ == Release 1.0.0: August 29, 2006
86
+
87
+ * Fix the parsing of the 'ps ax' system call. (thanks to Garance Alistair Drosehn)
88
+
89
+ == Release 0.4.4: February 14, 2006
90
+
91
+ * Several fixes that allow us to use the Daemons::Controller
92
+ with a proc instead of wrapping a script file. This gives us all the
93
+ PID file management, monitoring, command line options, etc. without having
94
+ to specify a path to our script which can be tricky, especially when using
95
+ RubyGems. (thanks to John-Mason Shackelford)
96
+
97
+ == Release 0.4.3: November 29, 2005
98
+
99
+ * New Option: You can specify the name of the application with :app_name
100
+ on calling Daemons.run. This will be used to contruct the name of the pid files
101
+ and log files. Defaults to the basename of the script. (thanks to Stephen R. Veit)
102
+
103
+ * Bugfix: Handle the case where no controller options are given when calling Daemons,
104
+ just options after "--". (thanks to Stephen R. Veit)
105
+
106
+
107
+ == Release 0.4.2: November 15, 2005
108
+
109
+ * Bugfix for problem with :normal pid-file directory mode (pid.rb), fixed (thanks to Stephen R. Veit)
110
+
111
+
112
+ == Release 0.4.1: September 11, 2005
113
+
114
+ * Bugfix for 'run' command line mode: didn't work anymore in 0.4.0, fixed
115
+
116
+
117
+ == Release 0.4.0: July 30, 2005
118
+
119
+ * Two completely new operation modes:
120
+ 1. Call a block as a daemon (<tt>Daemons.call { my_daemon_code }</tt>)
121
+ and control it from the parent process.
122
+ 2. Daemonize the currently running process (<tt>Daemons.daemonize</tt>)
123
+ plus the already existing mode to control your scripts (<tt>Daemons.run("script.rb")</tt>)
124
+ * Improved documentation (for example "How does the daemonization process work?")
125
+ * Improved "simulation mode" (<tt>:ontop</tt> option)
126
+ * Some minor bugfixes
127
+
128
+
129
+ == Release 0.3.0: April 21, 2005
130
+
131
+ * New monitor functionality: automatic restarting of your applications if they crash
132
+ * 'restart' command fixed
133
+ * '--force' command modifier (please refer to the documentation)
134
+ * Some more bugfixes and improvements
135
+
136
+
137
+ == Release 0.2.1: Mar 21, 2005
138
+
139
+ * Bugfix for a problem with the 'status' command
140
+
141
+
142
+ == Release 0.2.0: Mar 21, 2005
143
+
144
+ * Exception backtrace functionality added
145
+ * Exec functionality added
146
+ * More examples added
147
+ * New commands: status, zap
148
+
149
+
150
+ == Release 0.0.1: Feb 8, 2005
151
+
152
+ * Initial release
@@ -0,0 +1,2 @@
1
+ * put TODOS here
2
+
@@ -0,0 +1,468 @@
1
+ require 'daemons/pidfile'
2
+ require 'daemons/pidmem'
3
+ require 'daemons/change_privilege'
4
+
5
+ require 'timeout'
6
+
7
+
8
+ module Daemons
9
+
10
+ class Application
11
+
12
+ attr_accessor :app_argv
13
+ attr_accessor :controller_argv
14
+
15
+ # the Pid instance belonging to this application
16
+ attr_reader :pid
17
+
18
+ # the ApplicationGroup the application belongs to
19
+ attr_reader :group
20
+
21
+ # my private options
22
+ attr_reader :options
23
+
24
+
25
+ SIGNAL = (RUBY_PLATFORM =~ /win32/ ? 'KILL' : 'TERM')
26
+
27
+
28
+ def initialize(group, add_options = {}, pid = nil)
29
+ @group = group
30
+ @options = group.options.dup
31
+ @options.update(add_options)
32
+
33
+ @dir_mode = @dir = @script = nil
34
+
35
+ @force_kill_waittime = @options[:force_kill_waittime] || 20
36
+
37
+ unless @pid = pid
38
+ if @options[:no_pidfiles]
39
+ @pid = PidMem.new
40
+ elsif dir = pidfile_dir
41
+ @pid = PidFile.new(dir, @group.app_name, @group.multiple)
42
+ else
43
+ @pid = PidMem.new
44
+ end
45
+ end
46
+ end
47
+
48
+ def change_privilege
49
+ user = options[:user]
50
+ group = options[:group]
51
+ CurrentProcess.change_privilege(user, group) if user
52
+ end
53
+
54
+ def script
55
+ @script || @group.script
56
+ end
57
+
58
+ def pidfile_dir
59
+ Pid.dir(@dir_mode || @group.dir_mode, @dir || @group.dir, @script || @group.script)
60
+ end
61
+
62
+ def logdir
63
+ logdir = options[:log_dir]
64
+ unless logdir
65
+ logdir = options[:dir_mode] == :system ? '/var/log' : pidfile_dir
66
+ end
67
+ logdir
68
+ end
69
+
70
+ def output_logfile
71
+ (options[:log_output] && logdir) ? File.join(logdir, @group.app_name + '.output') : nil
72
+ end
73
+
74
+ def logfile
75
+ logdir ? File.join(logdir, @group.app_name + '.log') : nil
76
+ end
77
+
78
+ # this function is only used to daemonize the currently running process (Daemons.daemonize)
79
+ def start_none
80
+ unless options[:ontop]
81
+ Daemonize.daemonize(nil, @group.app_name) #(logfile)
82
+ else
83
+ Daemonize.simulate
84
+ end
85
+
86
+ @pid.pid = Process.pid
87
+
88
+
89
+ # We need this to remove the pid-file if the applications exits by itself.
90
+ # Note that <tt>at_text</tt> will only be run if the applications exits by calling
91
+ # <tt>exit</tt>, and not if it calls <tt>exit!</tt> (so please don't call <tt>exit!</tt>
92
+ # in your application!
93
+ #
94
+ at_exit {
95
+ begin; @pid.cleanup; rescue ::Exception; end
96
+
97
+ # If the option <tt>:backtrace</tt> is used and the application did exit by itself
98
+ # create a exception log.
99
+ if options[:backtrace] and not options[:ontop] and not $daemons_sigterm
100
+ begin; exception_log(); rescue ::Exception; end
101
+ end
102
+
103
+ }
104
+
105
+ # This part is needed to remove the pid-file if the application is killed by
106
+ # daemons or manually by the user.
107
+ # Note that the applications is not supposed to overwrite the signal handler for
108
+ # 'TERM'.
109
+ #
110
+ trap(SIGNAL) {
111
+ begin; @pid.cleanup; rescue ::Exception; end
112
+ $daemons_sigterm = true
113
+
114
+ if options[:hard_exit]
115
+ exit!
116
+ else
117
+ exit
118
+ end
119
+ }
120
+ end
121
+
122
+ def start_exec
123
+ if options[:backtrace]
124
+ puts "option :backtrace is not supported with :mode => :exec, ignoring"
125
+ end
126
+
127
+ unless options[:ontop]
128
+ Daemonize.daemonize(output_logfile, @group.app_name)
129
+ else
130
+ Daemonize.simulate(output_logfile)
131
+ end
132
+
133
+ # note that we cannot remove the pid file if we run in :ontop mode (i.e. 'ruby ctrl_exec.rb run')
134
+ @pid.pid = Process.pid
135
+
136
+ ENV['DAEMONS_ARGV'] = @controller_argv.join(' ')
137
+ # haven't tested yet if this is really passed to the exec'd process...
138
+
139
+ started()
140
+ Kernel.exec(script(), *(@app_argv || []))
141
+ #Kernel.exec(script(), *ARGV)
142
+ end
143
+
144
+ def start_load
145
+ unless options[:ontop]
146
+ Daemonize.daemonize(output_logfile, @group.app_name)
147
+ else
148
+ Daemonize.simulate(output_logfile)
149
+ end
150
+
151
+ @pid.pid = Process.pid
152
+
153
+
154
+ # We need this to remove the pid-file if the applications exits by itself.
155
+ # Note that <tt>at_exit</tt> will only be run if the applications exits by calling
156
+ # <tt>exit</tt>, and not if it calls <tt>exit!</tt> (so please don't call <tt>exit!</tt>
157
+ # in your application!
158
+ #
159
+ at_exit {
160
+ begin; @pid.cleanup; rescue ::Exception; end
161
+
162
+ # If the option <tt>:backtrace</tt> is used and the application did exit by itself
163
+ # create a exception log.
164
+ if options[:backtrace] and not options[:ontop] and not $daemons_sigterm
165
+ begin; exception_log(); rescue ::Exception; end
166
+ end
167
+
168
+ }
169
+
170
+ # This part is needed to remove the pid-file if the application is killed by
171
+ # daemons or manually by the user.
172
+ # Note that the applications is not supposed to overwrite the signal handler for
173
+ # 'TERM'.
174
+ #
175
+ $daemons_stop_proc = options[:stop_proc]
176
+ trap(SIGNAL) {
177
+ begin
178
+ if $daemons_stop_proc
179
+ $daemons_stop_proc.call
180
+ end
181
+ rescue ::Exception
182
+ end
183
+
184
+ begin; @pid.cleanup; rescue ::Exception; end
185
+ $daemons_sigterm = true
186
+
187
+ if options[:hard_exit]
188
+ exit!
189
+ else
190
+ exit
191
+ end
192
+ }
193
+
194
+ # Now we really start the script...
195
+ $DAEMONS_ARGV = @controller_argv
196
+ ENV['DAEMONS_ARGV'] = @controller_argv.join(' ')
197
+
198
+ ARGV.clear
199
+ ARGV.concat @app_argv if @app_argv
200
+
201
+ started()
202
+ # TODO: begin - rescue - end around this and exception logging
203
+ load script()
204
+ end
205
+
206
+ def start_proc
207
+ return unless p = options[:proc]
208
+
209
+ myproc = proc do
210
+ # We need this to remove the pid-file if the applications exits by itself.
211
+ # Note that <tt>at_text</tt> will only be run if the applications exits by calling
212
+ # <tt>exit</tt>, and not if it calls <tt>exit!</tt> (so please don't call <tt>exit!</tt>
213
+ # in your application!
214
+ #
215
+ at_exit {
216
+ begin; @pid.cleanup; rescue ::Exception; end
217
+
218
+ # If the option <tt>:backtrace</tt> is used and the application did exit by itself
219
+ # create a exception log.
220
+ if options[:backtrace] and not options[:ontop] and not $daemons_sigterm
221
+ begin; exception_log(); rescue ::Exception; end
222
+ end
223
+
224
+ }
225
+
226
+ # This part is needed to remove the pid-file if the application is killed by
227
+ # daemons or manually by the user.
228
+ # Note that the applications is not supposed to overwrite the signal handler for
229
+ # 'TERM'.
230
+ #
231
+ $daemons_stop_proc = options[:stop_proc]
232
+ trap(SIGNAL) {
233
+ begin
234
+ if $daemons_stop_proc
235
+ $daemons_stop_proc.call
236
+ end
237
+ rescue ::Exception
238
+ end
239
+
240
+ begin; @pid.cleanup; rescue ::Exception; end
241
+ $daemons_sigterm = true
242
+
243
+ if options[:hard_exit]
244
+ exit!
245
+ else
246
+ exit
247
+ end
248
+ }
249
+
250
+ p.call()
251
+ end
252
+
253
+ unless options[:ontop]
254
+ @pid.pid = Daemonize.call_as_daemon(myproc, output_logfile, @group.app_name)
255
+
256
+ else
257
+ Daemonize.simulate(output_logfile)
258
+
259
+ @pid.pid = Process.pid
260
+
261
+ myproc.call
262
+
263
+ # why did we use this??
264
+ # Thread.new(&options[:proc])
265
+
266
+ # why did we use the code below??
267
+ # unless pid = Process.fork
268
+ # @pid.pid = pid
269
+ # Daemonize.simulate(logfile)
270
+ # options[:proc].call
271
+ # exit
272
+ # else
273
+ # Process.detach(@pid.pid)
274
+ # end
275
+ end
276
+
277
+ started()
278
+ end
279
+
280
+
281
+ def start
282
+ change_privilege
283
+ @group.create_monitor(@group.applications[0] || self) unless options[:ontop] # we don't monitor applications in the foreground
284
+
285
+ case options[:mode]
286
+ when :none
287
+ # this is only used to daemonize the currently running process
288
+ start_none
289
+ when :exec
290
+ start_exec
291
+ when :load
292
+ start_load
293
+ when :proc
294
+ start_proc
295
+ else
296
+ start_load
297
+ end
298
+ end
299
+
300
+ def started
301
+ if pid = @pid.pid
302
+ puts "#{self.group.app_name}: process with pid #{pid} started."
303
+ STDOUT.flush
304
+ end
305
+ end
306
+
307
+
308
+ # def run
309
+ # if @group.controller.options[:exec]
310
+ # run_via_exec()
311
+ # else
312
+ # run_via_load()
313
+ # end
314
+ # end
315
+ #
316
+ # def run_via_exec
317
+ #
318
+ # end
319
+ #
320
+ # def run_via_load
321
+ #
322
+ # end
323
+
324
+ def reload
325
+ Process.kill('HUP', @pid.pid)
326
+ rescue
327
+ # ignore
328
+ end
329
+
330
+ # This is a nice little function for debugging purposes:
331
+ # In case a multi-threaded ruby script exits due to an uncaught exception
332
+ # it may be difficult to find out where the exception came from because
333
+ # one cannot catch exceptions that are thrown in threads other than the main
334
+ # thread.
335
+ #
336
+ # This function searches for all exceptions in memory and outputs them to STDERR
337
+ # (if it is connected) and to a log file in the pid-file directory.
338
+ #
339
+ def exception_log
340
+ return unless logfile
341
+
342
+ require 'logger'
343
+
344
+ l_file = Logger.new(logfile)
345
+
346
+ # the code below finds the last exception
347
+ e = nil
348
+
349
+ ObjectSpace.each_object {|o|
350
+ if ::Exception === o
351
+ e = o
352
+ end
353
+ }
354
+
355
+ l_file.info "*** below you find the most recent exception thrown, this will be likely (but not certainly) the exception that made the application exit abnormally ***"
356
+ l_file.error e
357
+
358
+ l_file.info "*** below you find all exception objects found in memory, some of them may have been thrown in your application, others may just be in memory because they are standard exceptions ***"
359
+
360
+ # this code logs every exception found in memory
361
+ ObjectSpace.each_object {|o|
362
+ if ::Exception === o
363
+ l_file.error o
364
+ end
365
+ }
366
+
367
+ l_file.close
368
+ end
369
+
370
+
371
+ def stop(no_wait = false)
372
+ if not running?
373
+ self.zap
374
+ return
375
+ end
376
+
377
+ pid = @pid.pid
378
+
379
+ # Catch errors when trying to kill a process that doesn't
380
+ # exist. This happens when the process quits and hasn't been
381
+ # restarted by the monitor yet. By catching the error, we allow the
382
+ # pid file clean-up to occur.
383
+ begin
384
+ Process.kill(SIGNAL, pid)
385
+ rescue Errno::ESRCH => e
386
+ puts "#{e} #{pid}"
387
+ puts "deleting pid-file."
388
+ end
389
+
390
+ if not no_wait
391
+ if @force_kill_waittime > 0
392
+ puts "#{self.group.app_name}: trying to stop process with pid #{pid}..."
393
+ STDOUT.flush
394
+
395
+ begin
396
+ Timeout::timeout(@force_kill_waittime) {
397
+ while @pid.running?
398
+ sleep(0.2)
399
+ end
400
+ }
401
+ rescue Timeout::Error
402
+ puts "#{self.group.app_name}: process with pid #{pid} won't stop, we forcefully kill it..."
403
+ STDOUT.flush
404
+
405
+ begin
406
+ Process.kill('KILL', pid)
407
+ rescue Errno::ESRCH
408
+ end
409
+
410
+ begin
411
+ Timeout::timeout(20) {
412
+ while @pid.running?
413
+ sleep(1)
414
+ end
415
+ }
416
+ rescue Timeout::Error
417
+ puts "#{self.group.app_name}: unable to forcefully kill process with pid #{pid}."
418
+ STDOUT.flush
419
+ end
420
+ end
421
+ end
422
+
423
+
424
+ end
425
+
426
+ sleep(0.1)
427
+ unless @pid.running?
428
+ # We try to remove the pid-files by ourselves, in case the application
429
+ # didn't clean it up.
430
+ begin; @pid.cleanup; rescue ::Exception; end
431
+
432
+ puts "#{self.group.app_name}: process with pid #{pid} successfully stopped."
433
+ STDOUT.flush
434
+ end
435
+
436
+ end
437
+
438
+ def zap
439
+ @pid.cleanup
440
+ end
441
+
442
+ def zap!
443
+ begin; @pid.cleanup; rescue ::Exception; end
444
+ end
445
+
446
+ def show_status
447
+ running = self.running?
448
+
449
+ puts "#{self.group.app_name}: #{running ? '' : 'not '}running#{(running and @pid.exist?) ? ' [pid ' + @pid.pid.to_s + ']' : ''}#{(@pid.exist? and not running) ? ' (but pid-file exists: ' + @pid.pid.to_s + ')' : ''}"
450
+ end
451
+
452
+ # This function implements a (probably too simle) method to detect
453
+ # whether the program with the pid found in the pid-file is still running.
454
+ # It just searches for the pid in the output of <tt>ps ax</tt>, which
455
+ # is probably not a good idea in some cases.
456
+ # Alternatives would be to use a direct access method the unix process control
457
+ # system.
458
+ #
459
+ def running?
460
+ if @pid.exist?
461
+ return Pid.running?(@pid.pid)
462
+ end
463
+
464
+ return false
465
+ end
466
+ end
467
+
468
+ end