diff --git a/lib/demon/base.rb b/lib/demon/base.rb index 188a27e9fe6..af4a73bb3cd 100644 --- a/lib/demon/base.rb +++ b/lib/demon/base.rb @@ -7,10 +7,10 @@ class Demon::Base @demons end - def self.start(count = 1) + def self.start(count = 1, verbose: false) @demons ||= {} count.times do |i| - (@demons["#{prefix}_#{i}"] ||= new(i)).start + (@demons["#{prefix}_#{i}"] ||= new(i, verbose: verbose)).start end end @@ -38,16 +38,18 @@ class Demon::Base attr_reader :pid, :parent_pid, :started, :index attr_accessor :stop_timeout - def initialize(index) + def initialize(index, rails_root: nil, parent_pid: nil, verbose: false) @index = index @pid = nil - @parent_pid = Process.pid + @parent_pid = parent_pid || Process.pid @started = false @stop_timeout = 10 + @rails_root = rails_root || Rails.root + @verbose = verbose end def pid_file - "#{Rails.root}/tmp/pids/#{self.class.prefix}_#{@index}.pid" + "#{@rails_root}/tmp/pids/#{self.class.prefix}_#{@index}.pid" end def alive?(pid = nil) @@ -153,8 +155,15 @@ class Demon::Base private + def verbose(msg) + if @verbose + puts msg + end + end + def write_pid_file - FileUtils.mkdir_p(Rails.root + "tmp/pids") + verbose("writing pid file #{pid_file} for #{@pid}") + FileUtils.mkdir_p(@rails_root + "tmp/pids") File.open(pid_file, 'w') do |f| f.write(@pid) end @@ -190,7 +199,7 @@ class Demon::Base end def establish_app - Discourse.after_fork + Discourse.after_fork if defined?(Discourse) Signal.trap("HUP") do begin diff --git a/script/demon_test/child b/script/demon_test/child new file mode 100755 index 00000000000..909d58f84b3 --- /dev/null +++ b/script/demon_test/child @@ -0,0 +1,31 @@ +#!/usr/bin/env ruby + +$parent_pid = ARGV[0].to_i + +puts "Hello from #{Process.pid} my parent is #{$parent_pid}" + +Thread.new do + + def alive?(pid) + Process.kill(0, pid) + true + rescue + false + end + + while true + begin + unless alive?($parent_pid) + STDERR.puts "Parent was terminated!" + Process.kill "TERM", Process.pid + sleep 10 + Process.kill "KILL", Process.pid + end + rescue => e + STDERR.puts "URGENT monitoring thread had an exception #{e}" + end + sleep 1 + end +end + +sleep diff --git a/script/demon_test/parent.rb b/script/demon_test/parent.rb new file mode 100644 index 00000000000..beb2658302f --- /dev/null +++ b/script/demon_test/parent.rb @@ -0,0 +1,25 @@ +require File.expand_path("../../../config/environment", __FILE__) + +puts "Parent is now loaded" + +class ForkExecDemon < Demon::Base + def self.prefix + "fork-exec-child" + end + + def run + if @pid = fork + write_pid_file + return + end + + exec "./child #{parent_pid}" + end +end + +ForkExecDemon.start(1, verbose: true) + +while true + ForkExecDemon.ensure_running + sleep 0.1 +end