t/lib.perl: FreeBSD: ignore accf_* messages
[unicorn.git] / lib / unicorn / configurator.rb
blobecdf03e6275da1cd954bc3abe4e6e0428c0598a4
1 # -*- encoding: binary -*-
2 require 'logger'
4 # Implements a simple DSL for configuring a unicorn server.
6 # See https://yhbt.net/unicorn/examples/unicorn.conf.rb and
7 # https://yhbt.net/unicorn/examples/unicorn.conf.minimal.rb
8 # example configuration files.  An example config file for use with
9 # nginx is also available at
10 # https://yhbt.net/unicorn/examples/nginx.conf
12 # See the link:/TUNING.html document for more information on tuning unicorn.
13 class Unicorn::Configurator
14   include Unicorn
16   # :stopdoc:
17   attr_accessor :set, :config_file, :after_reload
19   # used to stash stuff for deferred processing of cli options in
20   # config.ru after "working_directory" is bound.  Do not rely on
21   # this being around later on...
22   RACKUP = {
23     :daemonize => false,
24     :host => Unicorn::Const::DEFAULT_HOST,
25     :port => Unicorn::Const::DEFAULT_PORT,
26     :set_listener => false,
27     :options => { :listeners => [] }
28   }
30   # Default settings for Unicorn
31   DEFAULTS = {
32     :timeout => 60,
33     :logger => Logger.new($stderr),
34     :worker_processes => 1,
35     :after_fork => lambda { |server, worker|
36         server.logger.info("worker=#{worker.nr} spawned pid=#{$$}")
37       },
38     :before_fork => lambda { |server, worker|
39         server.logger.info("worker=#{worker.nr} spawning...")
40       },
41     :before_exec => lambda { |server|
42         server.logger.info("forked child re-executing...")
43       },
44     :after_worker_exit => lambda { |server, worker, status|
45         m = "reaped #{status.inspect} worker=#{worker.nr rescue 'unknown'}"
46         if status.success?
47           server.logger.info(m)
48         else
49           server.logger.error(m)
50         end
51       },
52     :after_worker_ready => lambda { |server, worker|
53         server.logger.info("worker=#{worker.nr} ready")
54       },
55     :pid => nil,
56     :early_hints => false,
57     :worker_exec => false,
58     :preload_app => false,
59     :check_client_connection => false,
60     :rewindable_input => true,
61     :client_body_buffer_size => Unicorn::Const::MAX_BODY,
62   }
63   #:startdoc:
65   def initialize(defaults = {}) #:nodoc:
66     self.set = Hash.new(:unset)
67     @use_defaults = defaults.delete(:use_defaults)
68     self.config_file = defaults.delete(:config_file)
70     # after_reload is only used by unicorn_rails, unsupported otherwise
71     self.after_reload = defaults.delete(:after_reload)
73     set.merge!(DEFAULTS) if @use_defaults
74     defaults.each { |key, value| self.__send__(key, value) }
75     Hash === set[:listener_opts] or
76         set[:listener_opts] = Hash.new { |hash,key| hash[key] = {} }
77     Array === set[:listeners] or set[:listeners] = []
78     reload(false)
79   end
81   def reload(merge_defaults = true) #:nodoc:
82     if merge_defaults && @use_defaults
83       set.merge!(DEFAULTS) if @use_defaults
84     end
85     instance_eval(File.read(config_file), config_file) if config_file
87     parse_rackup_file
89     RACKUP[:set_listener] and
90       set[:listeners] << "#{RACKUP[:host]}:#{RACKUP[:port]}"
92     RACKUP[:no_default_middleware] and
93       set[:default_middleware] = false
95     # unicorn_rails creates dirs here after working_directory is bound
96     after_reload.call if after_reload
98     # working_directory binds immediately (easier error checking that way),
99     # now ensure any paths we changed are correctly set.
100     [ :pid, :stderr_path, :stdout_path ].each do |var|
101       String === (path = set[var]) or next
102       path = File.expand_path(path)
103       File.writable?(path) || File.writable?(File.dirname(path)) or \
104             raise ArgumentError, "directory for #{var}=#{path} not writable"
105     end
106   end
108   def commit!(server, options = {}) #:nodoc:
109     skip = options[:skip] || []
110     if ready_pipe = RACKUP.delete(:ready_pipe)
111       server.ready_pipe = ready_pipe
112     end
113     if set[:check_client_connection]
114       set[:listeners].each do |address|
115         if set[:listener_opts][address][:tcp_nopush] == true
116           raise ArgumentError,
117             "check_client_connection is incompatible with tcp_nopush:true"
118         end
119       end
120     end
121     set.each do |key, value|
122       value == :unset and next
123       skip.include?(key) and next
124       server.__send__("#{key}=", value)
125     end
126   end
128   def [](key) # :nodoc:
129     set[key]
130   end
132   # sets object to the +obj+ Logger-like object.  The new Logger-like
133   # object must respond to the following methods:
134   # * debug
135   # * info
136   # * warn
137   # * error
138   # * fatal
139   # The default Logger will log its output to the path specified
140   # by +stderr_path+.  If you're running Unicorn daemonized, then
141   # you must specify a path to prevent error messages from going
142   # to /dev/null.
143   def logger(obj)
144     %w(debug info warn error fatal).each do |m|
145       obj.respond_to?(m) and next
146       raise ArgumentError, "logger=#{obj} does not respond to method=#{m}"
147     end
149     set[:logger] = obj
150   end
152   # sets after_fork hook to a given block.  This block will be called by
153   # the worker after forking.  The following is an example hook which adds
154   # a per-process listener to every worker:
155   #
156   #  after_fork do |server,worker|
157   #    # per-process listener ports for debugging/admin:
158   #    addr = "127.0.0.1:#{9293 + worker.nr}"
159   #
160   #    # the negative :tries parameter indicates we will retry forever
161   #    # waiting on the existing process to exit with a 5 second :delay
162   #    # Existing options for Unicorn::Configurator#listen such as
163   #    # :backlog, :rcvbuf, :sndbuf are available here as well.
164   #    server.listen(addr, :tries => -1, :delay => 5, :backlog => 128)
165   #  end
166   def after_fork(*args, &block)
167     set_hook(:after_fork, block_given? ? block : args[0])
168   end
170   # sets after_worker_exit hook to a given block.  This block will be called
171   # by the master process after a worker exits:
172   #
173   #  after_worker_exit do |server,worker,status|
174   #    # status is a Process::Status instance for the exited worker process
175   #    unless status.success?
176   #      server.logger.error("worker process failure: #{status.inspect}")
177   #    end
178   #  end
179   #
180   # after_worker_exit is only available in unicorn 5.3.0+
181   def after_worker_exit(*args, &block)
182     set_hook(:after_worker_exit, block_given? ? block : args[0], 3)
183   end
185   # sets after_worker_ready hook to a given block.  This block will be called
186   # by a worker process after it has been fully loaded, directly before it
187   # starts responding to requests:
188   #
189   #  after_worker_ready do |server,worker|
190   #    server.logger.info("worker #{worker.nr} ready, dropping privileges")
191   #    worker.user('username', 'groupname')
192   #  end
193   #
194   # Do not use Configurator#user if you rely on changing users in the
195   # after_worker_ready hook.
196   #
197   # after_worker_ready is only available in unicorn 5.3.0+
198   def after_worker_ready(*args, &block)
199     set_hook(:after_worker_ready, block_given? ? block : args[0])
200   end
202   # sets before_fork got be a given Proc object.  This Proc
203   # object will be called by the master process before forking
204   # each worker.
205   def before_fork(*args, &block)
206     set_hook(:before_fork, block_given? ? block : args[0])
207   end
209   # sets the before_exec hook to a given Proc object.  This
210   # Proc object will be called by the master process right
211   # before exec()-ing the new unicorn binary.  This is useful
212   # for freeing certain OS resources that you do NOT wish to
213   # share with the reexeced child process.
214   # There is no corresponding after_exec hook (for obvious reasons).
215   def before_exec(*args, &block)
216     set_hook(:before_exec, block_given? ? block : args[0], 1)
217   end
219   # sets the timeout of worker processes to +seconds+.  Workers
220   # handling the request/app.call/response cycle taking longer than
221   # this time period will be forcibly killed (via SIGKILL).  This
222   # timeout is enforced by the master process itself and not subject
223   # to the scheduling limitations by the worker process.  Due the
224   # low-complexity, low-overhead implementation, timeouts of less
225   # than 3.0 seconds can be considered inaccurate and unsafe.
226   #
227   # For running Unicorn behind nginx, it is recommended to set
228   # "fail_timeout=0" for in your nginx configuration like this
229   # to have nginx always retry backends that may have had workers
230   # SIGKILL-ed due to timeouts.
231   #
232   #    upstream unicorn_backend {
233   #      # for UNIX domain socket setups:
234   #      server unix:/path/to/.unicorn.sock fail_timeout=0;
235   #
236   #      # for TCP setups
237   #      server 192.168.0.7:8080 fail_timeout=0;
238   #      server 192.168.0.8:8080 fail_timeout=0;
239   #      server 192.168.0.9:8080 fail_timeout=0;
240   #    }
241   #
242   # See https://nginx.org/en/docs/http/ngx_http_upstream_module.html
243   # for more details on nginx upstream configuration.
244   def timeout(seconds)
245     set_int(:timeout, seconds, 3)
246     # POSIX says 31 days is the smallest allowed maximum timeout for select()
247     max = 30 * 60 * 60 * 24
248     set[:timeout] = seconds > max ? max : seconds
249   end
251   # Whether to exec in each worker process after forking.  This changes the
252   # memory layout of each worker process, which is a security feature designed
253   # to defeat possible address space discovery attacks.  Note that using
254   # worker_exec only makes sense if you are not preloading the application,
255   # and will result in higher memory usage.
256   #
257   # worker_exec is only available in unicorn 5.3.0+
258   def worker_exec(bool)
259     set_bool(:worker_exec, bool)
260   end
262   # sets the current number of worker_processes to +nr+.  Each worker
263   # process will serve exactly one client at a time.  You can
264   # increment or decrement this value at runtime by sending SIGTTIN
265   # or SIGTTOU respectively to the master process without reloading
266   # the rest of your Unicorn configuration.  See the SIGNALS document
267   # for more information.
268   def worker_processes(nr)
269     set_int(:worker_processes, nr, 1)
270   end
272   # sets whether to add default middleware in the development and
273   # deployment RACK_ENVs.
274   #
275   # default_middleware is only available in unicorn 5.5.0+
276   def default_middleware(bool)
277     set_bool(:default_middleware, bool)
278   end
280   # sets whether to enable the proposed early hints Rack API.
281   # If enabled, Rails 5.2+ will automatically send a 103 Early Hint
282   # for all the `javascript_include_tag` and `stylesheet_link_tag`
283   # in your response. See: https://api.rubyonrails.org/v5.2/classes/ActionDispatch/Request.html#method-i-send_early_hints
284   # See also https://tools.ietf.org/html/rfc8297
285   def early_hints(bool)
286     set_bool(:early_hints, bool)
287   end
289   # sets listeners to the given +addresses+, replacing or augmenting the
290   # current set.  This is for the global listener pool shared by all
291   # worker processes.  For per-worker listeners, see the after_fork example
292   # This is for internal API use only, do not use it in your Unicorn
293   # config file.  Use listen instead.
294   def listeners(addresses) # :nodoc:
295     Array === addresses or addresses = Array(addresses)
296     addresses.map! { |addr| expand_addr(addr) }
297     set[:listeners] = addresses
298   end
300   # Adds an +address+ to the existing listener set.  May be specified more
301   # than once.  +address+ may be an Integer port number for a TCP port, an
302   # "IP_ADDRESS:PORT" for TCP listeners or a pathname for UNIX domain sockets.
303   #
304   #   listen 3000 # listen to port 3000 on all TCP interfaces
305   #   listen "127.0.0.1:3000"  # listen to port 3000 on the loopback interface
306   #   listen "/path/to/.unicorn.sock" # listen on the given Unix domain socket
307   #   listen "[::1]:3000" # listen to port 3000 on the IPv6 loopback interface
308   #
309   # When using Unix domain sockets, be sure:
310   # 1) the path matches the one used by nginx
311   # 2) uses the same filesystem namespace as the nginx process
312   # For systemd users using PrivateTmp=true (for either nginx or unicorn),
313   # this means Unix domain sockets must not be placed in /tmp
314   #
315   # The following options may be specified (but are generally not needed):
316   #
317   # [:backlog => number of clients]
318   #
319   #   This is the backlog of the listen() syscall.
320   #
321   #   Some operating systems allow negative values here to specify the
322   #   maximum allowable value.  In most cases, this number is only
323   #   recommendation and there are other OS-specific tunables and
324   #   variables that can affect this number.  See the listen(2)
325   #   syscall documentation of your OS for the exact semantics of
326   #   this.
327   #
328   #   If you are running unicorn on multiple machines, lowering this number
329   #   can help your load balancer detect when a machine is overloaded
330   #   and give requests to a different machine.
331   #
332   #   Default: 1024
333   #
334   #   Note: with the Linux kernel, the net.core.somaxconn sysctl defaults
335   #   to 128, capping this value to 128.  Raising the sysctl allows a
336   #   larger backlog (which may not be desirable with multiple,
337   #   load-balanced machines).
338   #
339   # [:rcvbuf => bytes, :sndbuf => bytes]
340   #
341   #   Maximum receive and send buffer sizes (in bytes) of sockets.
342   #
343   #   These correspond to the SO_RCVBUF and SO_SNDBUF settings which
344   #   can be set via the setsockopt(2) syscall.  Some kernels
345   #   (e.g. Linux 2.4+) have intelligent auto-tuning mechanisms and
346   #   there is no need (and it is sometimes detrimental) to specify them.
347   #
348   #   See the socket API documentation of your operating system
349   #   to determine the exact semantics of these settings and
350   #   other operating system-specific knobs where they can be
351   #   specified.
352   #
353   #   Defaults: operating system defaults
354   #
355   # [:tcp_nodelay => true or false]
356   #
357   #   Disables Nagle's algorithm on TCP sockets if +true+.
358   #
359   #   Setting this to +true+ can make streaming responses in Rails 3.1
360   #   appear more quickly at the cost of slightly higher bandwidth usage.
361   #   The effect of this option is most visible if nginx is not used,
362   #   but nginx remains highly recommended with unicorn.
363   #
364   #   This has no effect on UNIX sockets.
365   #
366   #   Default: +true+ (Nagle's algorithm disabled) in unicorn
367   #   This defaulted to +false+ in unicorn 3.x
368   #
369   # [:tcp_nopush => true or false]
370   #
371   #   Enables/disables TCP_CORK in Linux or TCP_NOPUSH in FreeBSD
372   #
373   #   This prevents partial TCP frames from being sent out and reduces
374   #   wakeups in nginx if it is on a different machine.  Since unicorn
375   #   is only designed for applications that send the response body
376   #   quickly without keepalive, sockets will always be flushed on close
377   #   to prevent delays.
378   #
379   #   This has no effect on UNIX sockets.
380   #
381   #   Default: +false+
382   #   This defaulted to +true+ in unicorn 3.4 - 3.7
383   #
384   # [:ipv6only => true or false]
385   #
386   #   This option makes IPv6-capable TCP listeners IPv6-only and unable
387   #   to receive IPv4 queries on dual-stack systems.  A separate IPv4-only
388   #   listener is required if this is true.
389   #
390   #   Enabling this option for the IPv6-only listener and having a
391   #   separate IPv4 listener is recommended if you wish to support IPv6
392   #   on the same TCP port.  Otherwise, the value of \env[\"REMOTE_ADDR\"]
393   #   will appear as an ugly IPv4-mapped-IPv6 address for IPv4 clients
394   #   (e.g ":ffff:10.0.0.1" instead of just "10.0.0.1").
395   #
396   #   Default: Operating-system dependent
397   #
398   # [:reuseport => true or false]
399   #
400   #   This enables multiple, independently-started unicorn instances to
401   #   bind to the same port (as long as all the processes enable this).
402   #
403   #   This option must be used when unicorn first binds the listen socket.
404   #   It cannot be enabled when a socket is inherited via SIGUSR2
405   #   (but it will remain on if inherited), and it cannot be enabled
406   #   directly via SIGHUP.
407   #
408   #   Note: there is a chance of connections being dropped if
409   #   one of the unicorn instances is stopped while using this.
410   #
411   #   This is supported on *BSD systems and Linux 3.9 or later.
412   #
413   #   ref: https://lwn.net/Articles/542629/
414   #
415   #   Default: false (unset)
416   #
417   # [:tries => Integer]
418   #
419   #   Times to retry binding a socket if it is already in use
420   #
421   #   A negative number indicates we will retry indefinitely, this is
422   #   useful for migrations and upgrades when individual workers
423   #   are binding to different ports.
424   #
425   #   Default: 5
426   #
427   # [:delay => seconds]
428   #
429   #   Seconds to wait between successive +tries+
430   #
431   #   Default: 0.5 seconds
432   #
433   # [:umask => mode]
434   #
435   #   Sets the file mode creation mask for UNIX sockets.  If specified,
436   #   this is usually in octal notation.
437   #
438   #   Typically UNIX domain sockets are created with more liberal
439   #   file permissions than the rest of the application.  By default,
440   #   we create UNIX domain sockets to be readable and writable by
441   #   all local users to give them the same accessibility as
442   #   locally-bound TCP listeners.
443   #
444   #   This has no effect on TCP listeners.
445   #
446   #   Default: 0000 (world-read/writable)
447   #
448   # [:tcp_defer_accept => Integer]
449   #
450   #   Defer accept() until data is ready (Linux-only)
451   #
452   #   For Linux 2.6.32 and later, this is the number of retransmits to
453   #   defer an accept() for if no data arrives, but the client will
454   #   eventually be accepted after the specified number of retransmits
455   #   regardless of whether data is ready.
456   #
457   #   For Linux before 2.6.32, this is a boolean option, and
458   #   accepts are _always_ deferred indefinitely if no data arrives.
459   #   This is similar to <code>:accept_filter => "dataready"</code>
460   #   under FreeBSD.
461   #
462   #   Specifying +true+ is synonymous for the default value(s) below,
463   #   and +false+ or +nil+ is synonymous for a value of zero.
464   #
465   #   A value of +1+ is a good optimization for local networks
466   #   and trusted clients.  There is no good reason to ever
467   #   disable this with a +zero+ value with unicorn.
468   #
469   #   Default: 1
470   #
471   # [:accept_filter => String]
472   #
473   #   defer accept() until data is ready (FreeBSD-only)
474   #
475   #   This enables either the "dataready" or (default) "httpready"
476   #   accept() filter under FreeBSD.  This is intended as an
477   #   optimization to reduce context switches with common GET/HEAD
478   #   requests.
479   #
480   #   There is no good reason to change from the default.
481   #
482   #   Default: "httpready"
483   def listen(address, options = {})
484     address = expand_addr(address)
485     if String === address
486       [ :umask, :backlog, :sndbuf, :rcvbuf, :tries ].each do |key|
487         value = options[key] or next
488         Integer === value or
489           raise ArgumentError, "not an integer: #{key}=#{value.inspect}"
490       end
491       [ :tcp_nodelay, :tcp_nopush, :ipv6only, :reuseport ].each do |key|
492         (value = options[key]).nil? and next
493         TrueClass === value || FalseClass === value or
494           raise ArgumentError, "not boolean: #{key}=#{value.inspect}"
495       end
496       unless (value = options[:delay]).nil?
497         Numeric === value or
498           raise ArgumentError, "not numeric: delay=#{value.inspect}"
499       end
500       set[:listener_opts][address].merge!(options)
501     end
503     set[:listeners] << address
504   end
506   # sets the +path+ for the PID file of the unicorn master process
507   def pid(path); set_path(:pid, path); end
509   # Enabling this preloads an application before forking worker
510   # processes.  This allows memory savings when using a
511   # copy-on-write-friendly GC but can cause bad things to happen when
512   # resources like sockets are opened at load time by the master
513   # process and shared by multiple children.  People enabling this are
514   # highly encouraged to look at the before_fork/after_fork hooks to
515   # properly close/reopen sockets.  Files opened for logging do not
516   # have to be reopened as (unbuffered-in-userspace) files opened with
517   # the File::APPEND flag are written to atomically on UNIX.
518   #
519   # In addition to reloading the unicorn-specific config settings,
520   # SIGHUP will reload application code in the working
521   # directory/symlink when workers are gracefully restarted when
522   # preload_app=false (the default).  As reloading the application
523   # sometimes requires RubyGems updates, +Gem.refresh+ is always
524   # called before the application is loaded (for RubyGems users).
525   #
526   # During deployments, care should _always_ be taken to ensure your
527   # applications are properly deployed and running.  Using
528   # preload_app=false (the default) means you _must_ check if
529   # your application is responding properly after a deployment.
530   # Improperly deployed applications can go into a spawn loop
531   # if the application fails to load.  While your children are
532   # in a spawn loop, it is is possible to fix an application
533   # by properly deploying all required code and dependencies.
534   # Using preload_app=true means any application load error will
535   # cause the master process to exit with an error.
537   def preload_app(bool)
538     set_bool(:preload_app, bool)
539   end
541   # Toggles making \env[\"rack.input\"] rewindable.
542   # Disabling rewindability can improve performance by lowering
543   # I/O and memory usage for applications that accept uploads.
544   # Keep in mind that the Rack 1.x spec requires
545   # \env[\"rack.input\"] to be rewindable,
546   # but the Rack 2.x spec does not.
547   #
548   # +rewindable_input+ defaults to +true+ for compatibility.
549   # Setting it to +false+ may be safe for applications and
550   # frameworks developed for Rack 2.x and later.
551   def rewindable_input(bool)
552     set_bool(:rewindable_input, bool)
553   end
555   # The maximum size (in +bytes+) to buffer in memory before
556   # resorting to a temporary file.  Default is 112 kilobytes.
557   # This option has no effect if "rewindable_input" is set to
558   # +false+.
559   def client_body_buffer_size(bytes)
560     set_int(:client_body_buffer_size, bytes, 0)
561   end
563   # When enabled, unicorn will check the client connection by writing
564   # the beginning of the HTTP headers before calling the application.
565   #
566   # This will prevent calling the application for clients who have
567   # disconnected while their connection was queued.
568   #
569   # This only affects clients connecting over Unix domain sockets
570   # and TCP via loopback (127.*.*.*).  It is unlikely to detect
571   # disconnects if the client is on a remote host (even on a fast LAN).
572   #
573   # This option cannot be used in conjunction with :tcp_nopush.
574   def check_client_connection(bool)
575     set_bool(:check_client_connection, bool)
576   end
578   # Allow redirecting $stderr to a given path.  Unlike doing this from
579   # the shell, this allows the unicorn process to know the path its
580   # writing to and rotate the file if it is used for logging.  The
581   # file will be opened with the File::APPEND flag and writes
582   # synchronized to the kernel (but not necessarily to _disk_) so
583   # multiple processes can safely append to it.
584   #
585   # If you are daemonizing and using the default +logger+, it is important
586   # to specify this as errors will otherwise be lost to /dev/null.
587   # Some applications/libraries may also triggering warnings that go to
588   # stderr, and they will end up here.
589   def stderr_path(path)
590     set_path(:stderr_path, path)
591   end
593   # Same as stderr_path, except for $stdout.  Not many Rack applications
594   # write to $stdout, but any that do will have their output written here.
595   # It is safe to point this to the same location a stderr_path.
596   # Like stderr_path, this defaults to /dev/null when daemonized.
597   def stdout_path(path)
598     set_path(:stdout_path, path)
599   end
601   # sets the working directory for Unicorn.  This ensures SIGUSR2 will
602   # start a new instance of Unicorn in this directory.  This may be
603   # a symlink, a common scenario for Capistrano users.  Unlike
604   # all other Unicorn configuration directives, this binds immediately
605   # for error checking and cannot be undone by unsetting it in the
606   # configuration file and reloading.
607   def working_directory(path)
608     # just let chdir raise errors
609     path = File.expand_path(path)
610     if config_file &&
611        ! config_file.start_with?('/') &&
612        ! File.readable?("#{path}/#{config_file}")
613       raise ArgumentError,
614             "config_file=#{config_file} would not be accessible in" \
615             " working_directory=#{path}"
616     end
617     Dir.chdir(path)
618     Unicorn::HttpServer::START_CTX[:cwd] = ENV["PWD"] = path
619   end
621   # Runs worker processes as the specified +user+ and +group+.
622   # The master process always stays running as the user who started it.
623   # This switch will occur after calling the after_fork hook, and only
624   # if the Worker#user method is not called in the after_fork hook
625   # +group+ is optional and will not change if unspecified.
626   #
627   # Do not use Configurator#user if you rely on changing users in the
628   # after_worker_ready hook.  Instead, you need to call Worker#user
629   # directly in after_worker_ready.
630   def user(user, group = nil)
631     # raises ArgumentError on invalid user/group
632     Etc.getpwnam(user)
633     Etc.getgrnam(group) if group
634     set[:user] = [ user, group ]
635   end
637   # expands "unix:path/to/foo" to a socket relative to the current path
638   # expands pathnames of sockets if relative to "~" or "~username"
639   # expands "*:port and ":port" to "0.0.0.0:port"
640   def expand_addr(address) #:nodoc:
641     return "0.0.0.0:#{address}" if Integer === address
642     return address unless String === address
644     case address
645     when %r{\Aunix:(.*)\z}
646       File.expand_path($1)
647     when %r{\A~}
648       File.expand_path(address)
649     when %r{\A(?:\*:)?(\d+)\z}
650       "0.0.0.0:#$1"
651     when %r{\A\[([a-fA-F0-9:]+)\]\z}, %r/\A((?:\d+\.){3}\d+)\z/
652       canonicalize_tcp($1, 80)
653     when %r{\A\[([a-fA-F0-9:]+)\]:(\d+)\z}, %r{\A(.*):(\d+)\z}
654       canonicalize_tcp($1, $2.to_i)
655     else
656       address
657     end
658   end
660 private
661   def set_int(var, n, min) #:nodoc:
662     Integer === n or raise ArgumentError, "not an integer: #{var}=#{n.inspect}"
663     n >= min or raise ArgumentError, "too low (< #{min}): #{var}=#{n.inspect}"
664     set[var] = n
665   end
667   def canonicalize_tcp(addr, port)
668     packed = Socket.pack_sockaddr_in(port, addr)
669     port, addr = Socket.unpack_sockaddr_in(packed)
670     addr.include?(':') ? "[#{addr}]:#{port}" : "#{addr}:#{port}"
671   end
673   def set_path(var, path) #:nodoc:
674     case path
675     when NilClass, String
676       set[var] = path
677     else
678       raise ArgumentError
679     end
680   end
682   def check_bool(var, bool) # :nodoc:
683     case bool
684     when true, false
685       return bool
686     end
687     raise ArgumentError, "#{var}=#{bool.inspect} not a boolean"
688   end
690   def set_bool(var, bool) #:nodoc:
691     set[var] = check_bool(var, bool)
692   end
694   def set_hook(var, my_proc, req_arity = 2) #:nodoc:
695     case my_proc
696     when Proc
697       arity = my_proc.arity
698       (arity == req_arity) or \
699         raise ArgumentError,
700               "#{var}=#{my_proc.inspect} has invalid arity: " \
701               "#{arity} (need #{req_arity})"
702     when NilClass
703       my_proc = DEFAULTS[var]
704     else
705       raise ArgumentError, "invalid type: #{var}=#{my_proc.inspect}"
706     end
707     set[var] = my_proc
708   end
710   # this is called _after_ working_directory is bound.  This only
711   # parses the embedded switches in .ru files
712   # (for "rackup" compatibility)
713   def parse_rackup_file # :nodoc:
714     ru = RACKUP[:file] or return # we only return here in unit tests
716     # :rails means use (old) Rails autodetect
717     if ru == :rails
718       File.readable?('config.ru') or return
719       ru = 'config.ru'
720     end
722     File.readable?(ru) or
723       raise ArgumentError, "rackup file (#{ru}) not readable"
725     # it could be a .rb file, too, we don't parse those manually
726     ru.end_with?('.ru') or return
728     /^#\\(.*)/ =~ File.read(ru) or return
729     RACKUP[:optparse].parse!($1.split(/\s+/))
731     if RACKUP[:daemonize]
732       # unicorn_rails wants a default pid path, (not plain 'unicorn')
733       if after_reload
734         spid = set[:pid]
735         pid('tmp/pids/unicorn.pid') if spid.nil? || spid == :unset
736       end
737       unless RACKUP[:daemonized]
738         Unicorn::Launcher.daemonize!(RACKUP[:options])
739         RACKUP[:ready_pipe] = RACKUP[:options].delete(:ready_pipe)
740       end
741     end
742   end