There seems to be a small amount of confusion regarding how it''s used (and some of the code is not very obvious). So explain our usage of it and distinguish its use in the master vs worker(s). --- Hi Ryan, Great article[1] on Unicorn! I just noticed a small misunderstanding in how SELF_PIPE is used by the workers, so I just updated the RDoc to hopefully better describe it. I believe Unicorn is a great way to introduce Unix systems programming and you writing a great article is helping a lot :> As far as workers going down quickly in case the master dies unexpectedly: this is usually handled by checking the parent PID in the worker loop (which has a normal[2] upper bound of timeout(=default=60)/2.0 seconds per iteration on an idle server). Needing to get the workers to go down more quickly than that wasn''t too important to us, so I made the decision to not get fancier. [1] - for those on the mailing list who haven''t seen it: http://tomayko.com/writings/unicorn-is-unix [2] - for the case where speculative accept() is constantly successful, then this could be infinity as long as requests keep flowing in faster than they can be processed. Not that I expect anybody to care or hit this case (unexpectedly dead masters are very uncommon already :>). lib/unicorn.rb | 18 +++++++++++++++++- 1 files changed, 17 insertions(+), 1 deletions(-) diff --git a/lib/unicorn.rb b/lib/unicorn.rb index ddec8e9..d63567f 100644 --- a/lib/unicorn.rb +++ b/lib/unicorn.rb @@ -42,7 +42,23 @@ module Unicorn # This hash maps PIDs to Workers WORKERS = {} - # See: http://cr.yp.to/docs/selfpipe.html + # We use SELF_PIPE differently in the master and worker processes: + # + # * The master process never closes or reinitializes this once + # initialized. Signal handlers in the master process will write to + # it to wake up the master from IO.select in exactly the same manner + # djb describes in http://cr.yp.to/docs/selfpipe.html + # + # * The workers immediately close the pipe they inherit from the + # master and replace it with a new pipe after forking. This new + # pipe is also used to wakeup from IO.select from inside (worker) + # signal handlers. However, workers *close* the pipe descriptors in + # the signal handlers to raise EBADF in IO.select instead of writing + # like we do in the master. We cannot easily use the reader set for + # IO.select because LISTENERS is already that set, and it''s extra + # work (and cycles) to distinguish the pipe FD from the reader set + # once IO.select returns. So we''re lazy and just close the pipe when + # a (rare) signal arrives in the worker and reinitialize the pipe later. SELF_PIPE = [] # signal queue used for self-piping -- Eric Wong