1 # -*- encoding: binary -*-
3 $stdin.sync = $stdout.sync = $stderr.sync = true
10 class Unicorn::Launcher
12 # We don't do a lot of standard daemonization stuff:
13 # * umask is whatever was set by the parent process at startup
14 # and can be set in config.ru and config_file, so making it
15 # 0000 and potentially exposing sensitive log data can be bad
17 # * don't bother to chdir("/") here since unicorn is designed to
18 # run inside APP_ROOT. Unicorn will also re-chdir() to
19 # the directory it was started in when being re-executed
20 # to pickup code changes if the original deployment directory
21 # is a symlink or otherwise got replaced.
22 def self.daemonize!(options = {})
23 $stdin.reopen("/dev/null")
24 $stdin.sync = true # may not do anything...
26 # We only start a new process group if we're not being reexecuted
27 # and inheriting file descriptors from our parent
28 unless ENV['UNICORN_FD']
29 # grandparent - reads pipe, exits when master is ready
30 # \_ parent - exits immediately ASAP
31 # \_ unicorn master - writes to pipe when ready
36 wr.close # grandparent does not write
38 rd.close # unicorn master does not read
40 exit if fork # parent dies now
44 # this will block until HttpServer#join runs (or it dies)
45 master_pid = rd.sysread(16).to_i
46 exit!(1) unless master_pid > 1
48 else # unicorn master process
49 options[:ready_pipe] = wr
50 # $stderr/$stderr can/will be redirected separately in the
52 Unicorn::Configurator::DEFAULTS[:stderr_path] = "/dev/null"
53 Unicorn::Configurator::DEFAULTS[:stdout_path] = "/dev/null"
55 # returns so Unicorn.run can happen