Blogged by Ujihisa. Standard methods of programming and thoughts including Clojure, Vim, LLVM, Haskell, Ruby and Mathematics written by a Japanese programmer. github/ujihisa

Thursday, March 11, 2010

Double Fork Problem: Kill All Processes

Ruby forks a ruby process which also forks a process.

If you kill pid0, will the internal fork be automatically killed?

Try the previous code. This doesn't show 'bah!' message. It seems to be true that internal fork will be automatically killed. But it's wrong. This code doesn't show 'bah!' message just because the internal fork didn't started yet when Process.kill was called.

Try to wait until both blocks are certainly for forked.

This code shows 'bah!' message after the main routine finished!

So, let's think about how to kill the internal process.

  • The value of pid1 is not available in the outer main routine
  • An external command ps is not available in Windows
  • Usually the process ID pid0 and pid1 are sequential, but depending on it is dangerous

Here is the solution of it:

I added a line of at_exit. This is cumbersome a little bit, but safe and easy.

With Spawn

The previous discussion was actually for getting ready. Windows doesn't have fork. We can use spawn instead of fork in most cases.

This succeeded!

One More Thing

When you have to fork a ruby process with spawn, for example in case to rewrite fork to spawn, how do you write?

fork { p Dir.pwd }


spawn 'ruby', '-e', 'p Dir.pwd'

is not correct. The ruby that booted the code itself is not always 'ruby'. It can be ruby19, jruby, rbx or other rubies. In this case, your the following approach.

require 'rbconfig'
spawn RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['EXEEXT'], '-e', 'p Dir.pwd'


  1. > spawn Config::CONFIG['ruby_install_name'], '-e', 'p Dir.pwd'

    No. Remember "EXEEXT:"

    spawn Config::CONFIG["ruby_install_name"] + Config::CONFIG["EXEEXT"], '-e', 'p Dir.pwd'


    You may wish to use RbConfig.ruby after 1.9.2, or define it by your self.

  2. wow! I didn't notice EXEEXT! thx!

  3. I use IO.pipe:

  4. cool!

    I know that EventMachine is using this approach. IO.pipe is handy