about summary refs log tree commit homepage
path: root/lib
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2010-01-19 18:09:30 -0800
committerEric Wong <normalperson@yhbt.net>2010-01-19 18:31:36 -0800
commitcb6d8c71abac83d75d2bc990bdbc84748a1309ea (patch)
treeabf5469710b4bb68f0bbfe6650a8aa8ba7b4a2d3 /lib
parentaf637c8c64636a97c468e9126dfdc4575d1826aa (diff)
downloadunicorn-cb6d8c71abac83d75d2bc990bdbc84748a1309ea.tar.gz
This prevents trigger-happy init scripts from reading the pid
file (and thus sending signals) to a not-fully initialized
master process to handle them.

This does NOT fix anything if other processes are sending
signals prematurely without relying on the presence of the pid
file.  It's not possible to prevent all cases of this in one
process, even in a purely C application, so we won't bother
trying.

We continue to always defer signal handling to the main loop
anyways, and signals sent to the master process will be
deferred/ignored until Unicorn::HttpServer#join is run.
Diffstat (limited to 'lib')
-rw-r--r--lib/unicorn.rb16
1 files changed, 11 insertions, 5 deletions
diff --git a/lib/unicorn.rb b/lib/unicorn.rb
index 7a1ef34..e3e4315 100644
--- a/lib/unicorn.rb
+++ b/lib/unicorn.rb
@@ -210,7 +210,18 @@ module Unicorn
       end
       config_listeners.each { |addr| listen(addr) }
       raise ArgumentError, "no listeners" if LISTENERS.empty?
+
+      # this pipe is used to wake us up from select(2) in #join when signals
+      # are trapped.  See trap_deferred.
+      init_self_pipe!
+
+      # setup signal handlers before writing pid file in case people get
+      # trigger happy and send signals as soon as the pid file exists.
+      # Note that signals don't actually get handled until the #join method
+      QUEUE_SIGS.each { |sig| trap_deferred(sig) }
+      trap(:CHLD) { |_| awaken_master }
       self.pid = config[:pid]
+
       self.master_pid = $$
       build_app! if preload_app
       maintain_worker_count
@@ -322,14 +333,9 @@ module Unicorn
     # one-at-a-time time and we'll happily drop signals in case somebody
     # is signalling us too often.
     def join
-      # this pipe is used to wake us up from select(2) in #join when signals
-      # are trapped.  See trap_deferred
-      init_self_pipe!
       respawn = true
       last_check = Time.now
 
-      QUEUE_SIGS.each { |sig| trap_deferred(sig) }
-      trap(:CHLD) { |sig_nr| awaken_master }
       proc_name 'master'
       logger.info "master process ready" # test_exec.rb relies on this message
       if ready_pipe