Skip to content

Instantly share code, notes, and snippets.

@bkeepers
Created September 19, 2010 15:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bkeepers/d62f5f2c664134700ad3 to your computer and use it in GitHub Desktop.
Save bkeepers/d62f5f2c664134700ad3 to your computer and use it in GitHub Desktop.
children = {}
reap = lambda do
pid = Process.wait
i = children.delete(pid)
puts "Reaping #{i}: #{pid}"
children[fork { sleep rand(5) }] = i
end
trap :CLD do
reap.call
end
3.times do |i|
pid = fork { sleep rand(5) }
puts "Spawned #{i}: #{pid}"
children[pid] = i
end
loop do
reap.call
end
@guns
Copy link

guns commented Sep 21, 2010

A bomb-proof implementation: aggressively avoids zombies and hash misses.

#!/usr/bin/env ruby

children = {}
num_children = (arg = ARGV.first.to_i) > 1 ? arg : 1

child = lambda do |id, duration|
  fork do
    # reset traps inherited from parent
    trap :CLD, 'DEFAULT'

    $0 = "child.#{id}"
    sleep duration
    puts "[#{'%-.8f' % Time.now}] child.#{id} exit! PID [#{$$}]"
  end
end

trap :CLD do
  death = Time.now
  pids  = []

  begin
    # Avoid a SIGCLD race condition by collecting all available children
    while p = Process.wait(-1, Process::WNOHANG)
      pids << p
    end
  rescue
    retry
  end

  # we collected multiple pids and avoided a zombie!!!
  warn "####### #{pids.inspect}" if pids.size > 1

  # relaunch each dead child
  pids.each do |pid|
    # We're getting hash misses! I think it's a limitation of implementation;
    # so we just choose a new id and be done with it
    if not id = children.delete(pid)
      id = (num_children += 1)
      warn "####### HASH MISS FOR #{pid}; ASSIGNING ID #{id}"
    end

    duration = rand 5
    children[child.call id, duration] = id

    puts "[#{'%-.8f' % death}] child.#{id} SIGCLD! Restarting with sleep(#{duration})"
  end
end

1.upto num_children do |id|
  children[child.call id, rand(5)] = id
end

loop do
  sleep
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment