This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the unix category.
Last Updated: 2024-11-21
Imagine you have a typical multi-process server that forks off a process for every connection - e.g.
server = TCPServer.new("localhost", 8000)
loop do
client = server.accept
# Here is the fork
child_pid = fork do
client.puts "Hello"
client.close
end
end
Imagine you connect to this server using telnet
in another tab. Then you go
back to the original tab running the server and cause the server process to exit
(e.g. you defined a keyboard shortcut that calls exit
).
Will the connection between telnet
the forked child still work? I.e. will the
child survive its parent's death? The perhaps surprising answer is that yes, yes
it will. In general there is no automatic propogation of signals (SIGTERM or
otherwise) to children in the process tree
Inasmuch as killing a parent process can be observed to cause some children to
exit, this is due to ancillary effects -- such as SIGPIPEs being caused when the
child attempts to read or write to a pipeline with the dead parent on the other
side. Another confusing part is SIGINT
- i.e. the foreground ctrl-c
signal. This propagates to the entire process group,
therefore affects child processes). I.e. it is equivalent of calling kill
with a negative number!
If, on the other hand, you want the child processes to end with parent when exiting via a keyboard press, then create an exit handler or send a signal programatically in your keyboard handling code:
pids = []
Thread.new do
Thread.current.abort_on_exception = true
$stdin.getc == EXIT_CHARACTER
# 2nd args (pids) is a list of process ids that should receive the signal
Process.kill("INT", *pids)
end