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