Gary Wright
6/26/2005 3:53:00 PM
On Jun 26, 2005, at 6:28 AM, Yukihiro Matsumoto wrote:
> In message "Re: speeding up Process.detach frequency"
> on Sun, 26 Jun 2005 13:39:35 +0900, nobu.nokada@softhome.net
> writes:
> |> |It seems like a bug of Process.detach. After it received the
> |> |termination, it unnecessarily waits for one second again.
> |>
> |> Right. But using rb_waitpid() withouth WNOHANG does busy-wait.
> |
> |It should check periodically once per 0.06sec in
> |rb_thread_polling().
>
> Isn't it too often for most of the cases?
If the goal is simply to prevent zombie processes, then Process#detach
should just do a double fork. Here is an implementation of that
technique along with a couple other issues that are common when
creating a detached process (a daemon in Unix terminology):
def Process.daemon(dir="/")
return nil unless pid = fork {
setsid # become session leader of new session group
fork {
# second fork, ensures child is *not* the session leader
# then throw away references to the terminal or any other
# redirections.
[$stdin, $stdout, $stderr].each { |io| io.close }
Dir.chdir(dir);
File.umask(0)
yield if block_given?
}
exit(0)
}
wait(pid)
end
Standard practice is for a daemon is to close all open file
descriptors and then reopen what files are relevent for
the daemon (log files usually). Above I just closed stdin/out/err.
You could loop through all the open files and close them.
This method will make it easy to reopen stdin/stdout/stderr
to the locations expected by the daemon:
def Process.reopen(stdin=nil, stdout=nil, stderr=stdout)
$stdin = File.open(stdin || "/dev/null", "r")
$stdout = File.open(stdout || "/dev/null", "w")
$stderr = File.open(stderr || "/dev/null", "w")
end
Here is an example of using these two calls
Process.daemon {
Process.reopen(nil, "/tmp/logfile")
sleep 5;
puts "this goes to /tmp/logfile"
}
The interface to reopen could be different.
Gary Wright