#40 open
Jos Backus

Support running thin under daemontools/runit

Reported by Jos Backus | February 12th, 2008 @ 04:53 PM | in Ruby 1.9

It would be great to be able to run thin under a service manager such a daemontools/runit/launchd/AIX's SRC. The advantages of such an approach are:

  • Unified service control interface.
  • No use of pidfiles or process table scanning, both of which are brittle (stale pidfiles, pidfile/directory ownerships, issues, process name matching, ps output portability).
  • Direct notification (SIGCHLD, waitpid()) instead of polling.
  • Automated process restart capability, a la init.

To make thin play nice with this setup, thin should not background itself and instead wait for any children it forks (and restart them if they die, or alternatively exit so that the service manager can restart the cluster. This is similar to how Apache manages its worker children.

A stripped version of the run method in the swiftiply_mongrel_rails script is shown below to demonstrate the general pattern. In the example the manager doesn't bother to restart any children (hence the call to Process.waitall) but modifying it so that it would restart any dead children so that number_of_children are kept running at all times should not be hard. (One would fix the main loop to start processes while current_processes < wanted_processes and use Process.wait instead of Process.waitall at the bottom so that the loop is reentered after each child dies.)

Sample code:

  def self.run
    args = [ ... ]
    children = []
    number_of_children.times do |i|
      r, w = IO.pipe
      cid = fork
      unless cid # child
        w.close
        Thread.new {
          begin
            r.read # basically blocks until the parent disappears
          ensure
            STDERR.puts "pid #{Process.pid}: parent died... exiting!"
            Kernel.exit
          end
        }
        Mongrel::Runner.new.run(args) # never returns
        exit
      else
        r.close
        children << cid
      end
    end
    $stderr.puts "waiting for children: #{children.join(' ')}"
    Process.waitall
    $stderr.puts "all children exited."
  end

Comments and changes to this ticket

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile ยป

Pages