1 # -*- encoding: binary -*-
7 # version of Zbatery, currently 3.0.0
12 # runs the Zbatery HttpServer with +app+ and +options+ and does
13 # not return until the server has exited.
14 def run(app, options = {})
15 Rainbows::HttpServer.new(app, options).start.join
19 Rainbows::Const::RACK_DEFAULTS["SERVER_SOFTWARE"] = "Zbatery #{VERSION}"
21 # we don't actually fork workers, but allow using the
22 # {before,after}_fork hooks found in Unicorn/Rainbows!
24 FORK_HOOK = lambda { |_,_| }
28 # override stuff we don't need or can't use portably
32 # master == worker in our case
33 def init_worker_process(worker)
34 after_fork.call(self, worker)
35 worker.user(*user) if user.kind_of?(Array) && ! worker.switched
36 build_app! unless preload_app
37 Rainbows::Response.setup(self.class)
38 Rainbows::MaxBody.setup
39 Rainbows::RackInput.setup
40 Rainbows::ProcessClient.const_set(:APP, @app)
42 logger.info "Zbatery #@use worker_connections=#@worker_connections"
46 # we can't/don't need to do the fchmod heartbeat Unicorn/Rainbows! does
53 # this class is only used to avoid breaking Unicorn user switching
59 # only used if no concurrency model is specified
60 def worker_loop(worker)
61 init_worker_process(worker)
63 ret = IO.select(LISTENERS, nil, nil, nil) and
65 io = sock.kgio_tryaccept and process_client(io)
68 rescue Errno::EBADF, TypeError
71 Rainbows::Error.listen_loop(e)
72 end while Rainbows.alive
76 def maintain_worker_count; end
77 def init_self_pipe!; end
79 # can't just do a graceful exit if reopening logs fails, so we just
82 logger.info "reopening logs"
83 Unicorn::Util.reopen_logs
84 logger.info "done reopening logs"
86 logger.error "failed reopening logs #{e.message}"
89 def trap_deferred(sig)
94 trap(:INT) { stop(false) }
95 trap(:TERM) { stop(false) }
97 trap(:USR1) { reopen_logs }
98 trap(:USR2) { reexec }
99 trap(:HUP) { reexec; stop }
101 # technically feasible in some cases, just not sanely supportable:
102 %w(TTIN TTOU WINCH).each do |sig|
103 trap(sig) { logger.info "SIG#{sig} is not handled by Zbatery" }
107 ready_pipe.syswrite($$.to_s)
109 self.ready_pipe = nil
111 extend(Rainbows.const_get(@use))
112 worker = Worker.new(0, DeadIO.new)
113 before_fork.call(self, worker)
114 worker_loop(worker) # runs forever
117 def stop(graceful = true)
119 exit!(0) unless graceful
124 hook == Zbatery::FORK_HOOK or
125 logger.warn "calling before_fork without forking"
131 hook == Zbatery::FORK_HOOK or
132 logger.warn "calling after_fork without having forked"
138 Unicorn::Configurator::DEFAULTS[:before_fork] =
139 Unicorn::Configurator::DEFAULTS[:after_fork] = Zbatery::FORK_HOOK