lib/pitchfork.rb in pitchfork-0.9.0 vs lib/pitchfork.rb in pitchfork-0.10.0
- old
+ new
@@ -202,19 +202,36 @@
# to the master.
# This requires either PR_SET_CHILD_SUBREAPER which is exclusive to Linux 3.4
# or the master to be PID 1.
if middle_pid = FORK_LOCK.synchronize { Process.fork } # parent
# We need to wait(2) so that the middle process doesn't end up a zombie.
- Process.wait(middle_pid)
+ # The process only call fork again an exit so it should be pretty fast.
+ # However it might need to execute some `Process._fork` or `at_exit` callbacks,
+ # so it case it takes more than 5 seconds to exit, we kill it with SIGBUS
+ # to produce a crash report, as this is indicative of a nasty bug.
+ process_wait_with_timeout(middle_pid, 5, :BUS)
else # first child
+ Process.setproctitle("<pitchfork fork_sibling>")
clean_fork(&block) # detach into a grand child
exit
end
else
clean_fork(&block)
end
nil # it's tricky to return the PID
+ end
+
+ def process_wait_with_timeout(pid, timeout, timeout_signal = :KILL)
+ (timeout * 200).times do
+ status = Process.wait(pid, Process::WNOHANG)
+ return status if status
+ sleep 0.005 # 200 * 5ms => 1s
+ end
+
+ # The process didn't exit in the allotted time, so we kill it.
+ Process.kill(timeout_signal, pid)
+ Process.wait(pid)
end
def time_now(int = false)
Process.clock_gettime(Process::CLOCK_MONOTONIC, int ? :second : :float_second)
end