Skip to content

Instantly share code, notes, and snippets.

@somic
Created December 3, 2008 17:46

Revisions

  1. somic created this gist Dec 3, 2008.
    78 changes: 78 additions & 0 deletions forking_supervisor.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,78 @@
    #!/usr/bin/env ruby
    #
    # forking supervisor - forks workers and replaces dead workers.
    # start it in one console, send signals to it from another console.
    #

    require 'rubygems'
    require 'daemons/daemonize'


    def logit(msg)
    if $worker
    puts "#{Time.now} worker[#{$$}] #{msg}"
    else
    puts "#{Time.now} supervisor[#{$$}] #{msg}"
    end
    end

    def myworker
    # this is your worker, it does something useful
    loop {
    logit "ping"
    sleep 20
    }
    end

    def start_worker_daemon
    p = Process.fork { $worker = true; myworker }
    logit "started worker pid=#{p}"
    p
    end


    if __FILE__ == $0
    # starts supervisor
    Daemonize.daemonize(logfile_name="/tmp/my.log", app_name="foo") if
    ARGV[0] == '-d' # do you want supervisor as a daemon?

    logit "started"
    pids = Array.new
    workers = 3 # how many workers would you like today?
    logit "workers = #{workers}"
    $shutdown = false

    Signal.trap("TERM") {
    $shutdown = true
    if $worker
    # can do some worker cleanup here
    logit "Caught SIGTERM. Exiting."
    else
    logit "caught SIGTERM. Signaling child processes: #{pids.inspect}"
    pids.each { |pid|
    logit "sending SIGTERM to pid=#{pid}"
    Process.kill('TERM', pid)
    Process.waitpid(pid)
    logit "pid=#{pid} died."
    }
    logit "All child processes died."
    # can do some supervisor cleanup here
    end
    exit
    }

    Signal.trap('CLD') {
    unless $shutdown
    pids.delete(Process.wait)
    pids << start_worker_daemon
    end
    }

    while pids.size < workers
    pids << start_worker_daemon
    end

    loop { sleep 0x1000000 } rescue exit

    end