unicorn-maintained 6.2.0

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