Killing a parent process does not kill forked child

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-04-25

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

Resources