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
Say you had a program that spawned some child processes to do some work.
pids = []
work_items.each do |work_item|
command = handle(work_item)
# Create a child process
pid = Process.spawn(command)
pids << pid
end
At some point you wait for this work to be finished:
pids.each do |pid|
Process.waitpid(pid)
puts "Finished #{pid}"
end
What's the confusing part here? Well imagine the 1st process was the slowest
(10s) and the 4th in the pids
array the fastest (1s). That information gets
lost because we stop on the first entry in the array and wait 10s. As soon as that's
finished, you'll see the others seemingly "finish" instantaneously, obscuring
the fact that the 4th finished much sooner (and blocked progress)
One solution is to wait for any child process (i.e. the next one that finishes)
begin
# give -1 as an argument waits for _any_ PID
Process.waitpid(-1)
end until pids.empty?