1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 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 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
require 'daemons/exceptions'
module Daemons
require 'daemons/daemonize'
class Monitor
def self.find(dir, app_name)
pid = PidFile.find_files(dir, app_name, false)[0]
if pid
pid = PidFile.existing(pid)
unless PidFile.running?(pid.pid)
begin; pid.cleanup; rescue ::Exception; end
return
end
monitor = allocate
monitor.instance_variable_set(:@pid, pid)
return monitor
end
nil
end
def initialize(an_app, options = {})
@app = an_app
@app_name = an_app.group.app_name + '_monitor'
@monitor_interval = options[:monitor_interval] || 30
if an_app.pidfile_dir
@pid = PidFile.new(an_app.pidfile_dir, @app_name, false)
else
@pid = PidMem.new
end
end
def watch(application_group)
sleep(5)
loop do
application_group.applications.each do |a|
unless a.running?
a.zap!
sleep(1)
Process.detach(fork { a.start(true) })
sleep(5)
end
end
sleep(@monitor_interval)
end
end
private :watch
def start_with_pidfile(application_group)
fork do
Daemonize.daemonize(nil, @app_name)
begin
@pid.pid = Process.pid
watch(application_group)
rescue ::Exception => e
begin
File.open(@app.logfile, 'a') do |f|
f.puts Time.now
f.puts e
f.puts e.backtrace.inspect
end
ensure
begin; @pid.cleanup; rescue ::Exception; end
exit!
end
end
end
end
private :start_with_pidfile
def start_without_pidfile(application_group)
Thread.new { watch(application_group) }
end
private :start_without_pidfile
def start(application_group)
return if application_group.applications.empty?
if @pid.kind_of?(PidFile)
start_with_pidfile(application_group)
else
start_without_pidfile(application_group)
end
end
def stop
begin
pid = @pid.pid
Process.kill(Application::SIGNAL, pid)
Timeout.timeout(5, TimeoutError) do
while Pid.running?(pid)
sleep(0.1)
end
end
rescue ::Exception => e
$stderr.puts "exception while trying to stop monitor process #{pid}: #{e}"
$stderr.puts "deleting pid-file."
end
# We try to remove the pid-files by ourselves, in case the monitor
# didn't clean it up.
begin; @pid.zap; rescue ::Exception; end
end
end
end
|