I want to offload a block of code in my main process to child process to make it run concurrently. I also want to have the PID of the spawned child process so I can monitor and kill it if necessary.
4 Answers
In addition to Chris' great answer, remember to call Process.wait
from your master in order to reap your child process, else you'll leave zombies behind.
Example as requested in comments:
pid = Process.fork do
puts "child, pid #{Process.pid} sleeping..."
sleep 5
puts "child exiting"
end
puts "parent, pid #{Process.pid}, waiting on child pid #{pid}"
Process.wait
puts "parent exiting"

- 5,893
- 1
- 28
- 32
-
Sweet, that was an awesome tip. – Chris Lloyd Nov 23 '08 at 09:15
-
1Where and how would you place Process.wait in the accepted answer above? – iamtoc Oct 11 '12 at 23:29
-
11Note that `Process.wait` without an argument waits for _any_ child, so in a more general case, this code snippet would exit the parent even if that specific child process above doesn't exit. A more exact version would say `Process.wait(pid)` instead. – sameers Nov 21 '14 at 18:10
-
Is there a platform-independent way to do this (i.e. without `fork`, since that's only on Unix)? – Nic Dec 17 '15 at 01:48
-
4Let's agree in `Process.waitall`. The parent will wait until **ALL** childs exit. – Carlos Troncoso Nov 13 '16 at 04:53
You can use the fork
kernel method. Here is an example:
#!/usr/bin/env ruby
puts "This is the master process."
child_pid = fork do
puts "This is the child process"
exit
end
puts "The PID of the child process is #{child_pid}"
The fork
method returns the PID of the process it forks and executes any code in the block passed. Like regular Ruby blocks it keeps the bindings of the parent process.
It is a good idea to make your forked process exit
.

- 12,100
- 7
- 36
- 32
-
1One thing to remember with Ruby is that not all things work exactly the same way in Windows versus *nix. Sometimes they're completely unimplemented on Windows, so use at your own peril. – Dominik Grabiec Nov 22 '08 at 17:33
-
6
-
I'm a bit confused about calling `exit` - why (or when) is it needed? – skwisgaar Oct 30 '16 at 19:55
-
2@skwisgaar `exit` is needed to ensure the forked process terminates. You may end up with zombie or orphan processes otherwise. More at: http://stackoverflow.com/a/20689837/3784008. Short explanation: call `exit` inside your forked process after it finishes running its code, or the new `ruby` process that was spawned will continue running in the background. – anothermh Feb 04 '17 at 00:00
-
1`exit` with default code is not necessary with this form of fork, as " block is run in the subprocess, and the subprocess terminates with a status of zero." To avoid creating a zombie you need to either `Process.wait` or `Process.detach` in the parent process. http://ruby-doc.org/core-2.2.3/Kernel.html#method-i-fork – artm Mar 21 '18 at 12:01
-
In 1.9 you can use Process.spawn command. See also http://en.wikibooks.org/wiki/Ruby_Programming/Running_Multiple_Processes

- 62,887
- 36
- 269
- 388
If you are happy to use Threads, rather than Processes, then something like this may be a bit more scaleable to more-than-one fork:
def doit(x)
sleep(rand(10))
puts "Done... #{x}"
end
thingstodo = ["a","b","c","d","e","f","g"]
tasklist = []
# Set the threads going
thingstodo.each { |thing|
task = Thread.new(thing) { |this| doit(this) }
tasklist << task
}
# Wait for the threads to finish
tasklist.each { |task|
task.join
}
Please see John Topley's excellent comments and reference, below, regarding the Ruby execution model and its restrictions.
Just edited to correct a glaring error (no assignment to task), and to follow @(Jason King)'s advice.

- 9,567
- 10
- 42
- 62
-
-
2Read this regarding Ruby 1.9: http://www.igvita.com/2008/11/13/concurrency-is-a-myth-in-ruby/ – John Topley Nov 22 '08 at 11:47
-
Should be: `Thread.new(thing) { |it| doit(it) }` Because `thing` is reset on each iteration, so there's no guarantee that the right thread will get the right `thing` – smathy Sep 18 '10 at 00:16