example/kill_child.rb in frontkick-0.5.1 vs example/kill_child.rb in frontkick-0.5.2

- old
+ new

@@ -1,51 +1,77 @@ require 'frontkick' -puts "kill -TERM #{Process.pid} or Hit Ctrl-C in 10 seconds" +class SignalHandler + def self.register + @pids ||= [] + @main_threads ||= [] -result = Frontkick.exec(["sleep 10"]) do |wait_thr| - pid = wait_thr.pid - signal_pipe_r, signal_pipe_w = IO.pipe + if @signal_pipe_r.nil? and @signal_pipe_w.nil? + @signal_pipe_r, @signal_pipe_w = IO.pipe + end - # You know, there are many things `can't be called from trap context` - trap :INT do - signal_pipe_w.puts 'INT' + # For example, loogger `can't be called from trap context` + trap :INT do + @signal_pipe_w.puts 'INT' + end + trap :TERM do + @signal_pipe_w.puts 'TERM' + end + + # Create a new thread to handle signals + # This example kills child (and self) + @signal_handler_thr ||= Thread.new do + begin + while readable_io = IO.select([@signal_pipe_r]) + signal = readable_io.first[0].gets.strip + puts "#{signal} signal received" + @pids.each_with_index do |pid, idx| + main_thread = @main_threads[idx] + begin + puts "kill -#{signal} #{pid}" + Process.kill(signal, pid) rescue nil + rescue => e + main_thread.raise e + end + end + # case signal + # when 'INT' + # Kernel.exit(130) + # when 'TERM' + # Kernel.exit(148) + # end + end + rescue Exception => e + Thread.main.raise e + end + end end - trap :TERM do - signal_pipe_w.puts 'TERM' + + def self.push(pid) + @pids << pid + @main_threads << Thread.current end - # Create a new thread to handle signals - # This example kills child and self - signal_handler_thr = Thread.new do - readable_io = IO.select([signal_pipe_r]) - signal = readable_io.first[0].gets.strip - case signal - when 'INT' - puts "kill -INT #{pid}" - Process.kill('INT', pid) rescue nil - pid, status = Process.waitpid2(pid) rescue nil - Kernel.exit(130) - when 'TERM' - puts "kill -TERM #{pid}" - Process.kill('TERM', pid) rescue nil - pid, status = Process.waitpid2(pid) rescue nil - Kernel.exit(148) - end + def self.pop(pid) + @pids -= [pid] + @main_threads -= [Thread.current] end +end - begin - # Wait child to finish (for normal situation) - wait_thr.join +SignalHandler.register - # Send NOOP to finish signal_handler_thr (for normal situation) - signal_pipe_w.puts 'NOOP' - signal_handler_thr.join +puts "## Frontkick started" +puts "kill -TERM #{Process.pid} or Hit Ctrl-C in 10 seconds" +result = Frontkick.exec(["sleep 10"]) do |wait_thr| + begin + SignalHandler.push(wait_thr.pid) + puts wait_thr.value # wait child to finish (for normal situation) ensure - signal_pipe_r.close rescue nil - signal_pipe_w.close rescue nil + SignalHandler.pop(wait_thr.pid) end end -# should come here if child process finished normally, -# but not come here if signals are received (Kernel.exit) +puts "## Fronkick finished" +puts "kill -TERM #{Process.pid} or Hit Ctrl-C in 5 seconds" +sleep 5 + puts result.inspect