1 # -*- encoding: binary -*-
2 # frozen_string_literal: false
5 $stdout.sync = $stderr.sync = true
12 module Unicorn::Launcher
14 # We don't do a lot of standard daemonization stuff:
15 # * umask is whatever was set by the parent process at startup
16 # and can be set in config.ru and config_file, so making it
17 # 0000 and potentially exposing sensitive log data can be bad
19 # * don't bother to chdir("/") here since unicorn is designed to
20 # run inside APP_ROOT. Unicorn will also re-chdir() to
21 # the directory it was started in when being re-executed
22 # to pickup code changes if the original deployment directory
23 # is a symlink or otherwise got replaced.
24 def self.daemonize!(options)
25 cfg = Unicorn::Configurator
26 $stdin.reopen("/dev/null")
28 # We only start a new process group if we're not being reexecuted
29 # and inheriting file descriptors from our parent
30 unless ENV['UNICORN_FD']
31 # grandparent - reads pipe, exits when master is ready
32 # \_ parent - exits immediately ASAP
33 # \_ unicorn master - writes to pipe when ready
38 wr.close # grandparent does not write
40 rd.close # unicorn master does not read
42 exit if fork # parent dies now
46 # this will block until HttpServer#join runs (or it dies)
47 master_pid = (rd.readpartial(16) rescue nil).to_i
49 warn "master failed to start, check stderr log for details"
53 else # unicorn master process
54 options[:ready_pipe] = wr
57 # $stderr/$stderr can/will be redirected separately in the Unicorn config
58 cfg::DEFAULTS[:stderr_path] ||= "/dev/null"
59 cfg::DEFAULTS[:stdout_path] ||= "/dev/null"
60 cfg::RACKUP[:daemonized] = true