unicorn-rupcio 6.1.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 (145) 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 +144 -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 +318 -0
  20. data/HACKING +117 -0
  21. data/ISSUES +102 -0
  22. data/KNOWN_ISSUES +79 -0
  23. data/LICENSE +67 -0
  24. data/Links +58 -0
  25. data/PHILOSOPHY +139 -0
  26. data/README +165 -0
  27. data/Rakefile +17 -0
  28. data/SIGNALS +123 -0
  29. data/Sandbox +104 -0
  30. data/TODO +1 -0
  31. data/TUNING +119 -0
  32. data/archive/.gitignore +3 -0
  33. data/archive/slrnpull.conf +4 -0
  34. data/bin/unicorn +129 -0
  35. data/bin/unicorn_rails +210 -0
  36. data/examples/big_app_gc.rb +3 -0
  37. data/examples/echo.ru +27 -0
  38. data/examples/init.sh +102 -0
  39. data/examples/logger_mp_safe.rb +26 -0
  40. data/examples/logrotate.conf +44 -0
  41. data/examples/nginx.conf +156 -0
  42. data/examples/unicorn.conf.minimal.rb +14 -0
  43. data/examples/unicorn.conf.rb +111 -0
  44. data/examples/unicorn.socket +11 -0
  45. data/examples/unicorn@.service +40 -0
  46. data/ext/unicorn_http/CFLAGS +13 -0
  47. data/ext/unicorn_http/c_util.h +115 -0
  48. data/ext/unicorn_http/common_field_optimization.h +128 -0
  49. data/ext/unicorn_http/epollexclusive.h +128 -0
  50. data/ext/unicorn_http/ext_help.h +38 -0
  51. data/ext/unicorn_http/extconf.rb +40 -0
  52. data/ext/unicorn_http/global_variables.h +97 -0
  53. data/ext/unicorn_http/httpdate.c +91 -0
  54. data/ext/unicorn_http/unicorn_http.c +4348 -0
  55. data/ext/unicorn_http/unicorn_http.rl +1054 -0
  56. data/ext/unicorn_http/unicorn_http_common.rl +76 -0
  57. data/lib/unicorn/app/old_rails/static.rb +60 -0
  58. data/lib/unicorn/app/old_rails.rb +36 -0
  59. data/lib/unicorn/cgi_wrapper.rb +148 -0
  60. data/lib/unicorn/configurator.rb +749 -0
  61. data/lib/unicorn/const.rb +22 -0
  62. data/lib/unicorn/http_request.rb +180 -0
  63. data/lib/unicorn/http_response.rb +95 -0
  64. data/lib/unicorn/http_server.rb +860 -0
  65. data/lib/unicorn/launcher.rb +63 -0
  66. data/lib/unicorn/oob_gc.rb +82 -0
  67. data/lib/unicorn/preread_input.rb +34 -0
  68. data/lib/unicorn/select_waiter.rb +7 -0
  69. data/lib/unicorn/socket_helper.rb +186 -0
  70. data/lib/unicorn/stream_input.rb +152 -0
  71. data/lib/unicorn/tee_input.rb +132 -0
  72. data/lib/unicorn/tmpio.rb +34 -0
  73. data/lib/unicorn/util.rb +91 -0
  74. data/lib/unicorn/version.rb +1 -0
  75. data/lib/unicorn/worker.rb +166 -0
  76. data/lib/unicorn.rb +137 -0
  77. data/man/man1/unicorn.1 +222 -0
  78. data/man/man1/unicorn_rails.1 +207 -0
  79. data/setup.rb +1587 -0
  80. data/t/.gitignore +4 -0
  81. data/t/GNUmakefile +5 -0
  82. data/t/README +49 -0
  83. data/t/active-unix-socket.t +110 -0
  84. data/t/back-out-of-upgrade.t +44 -0
  85. data/t/bin/unused_listen +40 -0
  86. data/t/client_body_buffer_size.ru +15 -0
  87. data/t/client_body_buffer_size.t +79 -0
  88. data/t/detach.ru +12 -0
  89. data/t/env.ru +4 -0
  90. data/t/fails-rack-lint.ru +6 -0
  91. data/t/heartbeat-timeout.ru +13 -0
  92. data/t/heartbeat-timeout.t +60 -0
  93. data/t/integration.ru +129 -0
  94. data/t/integration.t +509 -0
  95. data/t/lib.perl +309 -0
  96. data/t/listener_names.ru +5 -0
  97. data/t/my-tap-lib.sh +201 -0
  98. data/t/oob_gc.ru +18 -0
  99. data/t/oob_gc_path.ru +18 -0
  100. data/t/pid.ru +4 -0
  101. data/t/preread_input.ru +23 -0
  102. data/t/reload-bad-config.t +49 -0
  103. data/t/reopen-logs.ru +14 -0
  104. data/t/reopen-logs.t +36 -0
  105. data/t/t0010-reap-logging.sh +55 -0
  106. data/t/t0012-reload-empty-config.sh +86 -0
  107. data/t/t0013-rewindable-input-false.sh +24 -0
  108. data/t/t0013.ru +13 -0
  109. data/t/t0014-rewindable-input-true.sh +24 -0
  110. data/t/t0014.ru +13 -0
  111. data/t/t0015-configurator-internals.sh +25 -0
  112. data/t/t0020-at_exit-handler.sh +49 -0
  113. data/t/t0021-process_detach.sh +29 -0
  114. data/t/t0022-listener_names-preload_app.sh +32 -0
  115. data/t/t0300-no-default-middleware.sh +20 -0
  116. data/t/t0301-no-default-middleware-ignored-in-config.sh +25 -0
  117. data/t/t0301.ru +14 -0
  118. data/t/t9001-oob_gc.sh +47 -0
  119. data/t/t9002-oob_gc-path.sh +75 -0
  120. data/t/test-lib.sh +125 -0
  121. data/t/winch_ttin.t +64 -0
  122. data/t/working_directory.t +86 -0
  123. data/test/aggregate.rb +16 -0
  124. data/test/benchmark/README +60 -0
  125. data/test/benchmark/dd.ru +19 -0
  126. data/test/benchmark/ddstream.ru +51 -0
  127. data/test/benchmark/readinput.ru +41 -0
  128. data/test/benchmark/stack.ru +9 -0
  129. data/test/benchmark/uconnect.perl +66 -0
  130. data/test/exec/README +5 -0
  131. data/test/exec/test_exec.rb +1030 -0
  132. data/test/test_helper.rb +307 -0
  133. data/test/unit/test_configurator.rb +176 -0
  134. data/test/unit/test_droplet.rb +29 -0
  135. data/test/unit/test_http_parser.rb +885 -0
  136. data/test/unit/test_http_parser_ng.rb +715 -0
  137. data/test/unit/test_server.rb +245 -0
  138. data/test/unit/test_signals.rb +189 -0
  139. data/test/unit/test_socket_helper.rb +160 -0
  140. data/test/unit/test_stream_input.rb +211 -0
  141. data/test/unit/test_tee_input.rb +304 -0
  142. data/test/unit/test_util.rb +132 -0
  143. data/test/unit/test_waiter.rb +35 -0
  144. data/unicorn.gemspec +49 -0
  145. metadata +266 -0
data/TUNING ADDED
@@ -0,0 +1,119 @@
1
+ = Tuning unicorn
2
+
3
+ unicorn performance is generally as good as a (mostly) Ruby web server
4
+ can provide. Most often the performance bottleneck is in the web
5
+ application running on Unicorn rather than Unicorn itself.
6
+
7
+ == unicorn Configuration
8
+
9
+ See Unicorn::Configurator for details on the config file format.
10
+ +worker_processes+ is the most-commonly needed tuning parameter.
11
+
12
+ === Unicorn::Configurator#worker_processes
13
+
14
+ * worker_processes should be scaled to the number of processes your
15
+ backend system(s) can support. DO NOT scale it to the number of
16
+ external network clients your application expects to be serving.
17
+ unicorn is NOT for serving slow clients, that is the job of nginx.
18
+
19
+ * worker_processes should be *at* *least* the number of CPU cores on
20
+ a dedicated server (unless you do not have enough memory).
21
+ If your application has occasionally slow responses that are /not/
22
+ CPU-intensive, you may increase this to workaround those inefficiencies.
23
+
24
+ * Under Ruby 2.2 or later, Etc.nprocessors may be used to determine
25
+ the number of CPU cores present.
26
+
27
+ * worker_processes may be increased for Unicorn::OobGC users to provide
28
+ more consistent response times.
29
+
30
+ * Never, ever, increase worker_processes to the point where the system
31
+ runs out of physical memory and hits swap. Production servers should
32
+ never see heavy swap activity.
33
+
34
+ === Unicorn::Configurator#listen Options
35
+
36
+ * Setting a very low value for the :backlog parameter in "listen"
37
+ directives can allow failover to happen more quickly if your
38
+ cluster is configured for it.
39
+
40
+ * If you're doing extremely simple benchmarks and getting connection
41
+ errors under high request rates, increasing your :backlog parameter
42
+ above the already-generous default of 1024 can help avoid connection
43
+ errors. Keep in mind this is not recommended for real traffic if
44
+ you have another machine to failover to (see above).
45
+
46
+ * :rcvbuf and :sndbuf parameters generally do not need to be set for TCP
47
+ listeners under Linux 2.6 because auto-tuning is enabled. UNIX domain
48
+ sockets do not have auto-tuning buffer sizes; so increasing those will
49
+ allow syscalls and task switches to be saved for larger requests
50
+ and responses. If your app only generates small responses or expects
51
+ small requests, you may shrink the buffer sizes to save memory, too.
52
+
53
+ * Having socket buffers too large can also be detrimental or have
54
+ little effect. Huge buffers can put more pressure on the allocator
55
+ and may also thrash CPU caches, cancelling out performance gains
56
+ one would normally expect.
57
+
58
+ * UNIX domain sockets are slightly faster than TCP sockets, but only
59
+ work if nginx is on the same machine.
60
+
61
+ == Other unicorn settings
62
+
63
+ * Setting "preload_app true" can allow copy-on-write-friendly GC to
64
+ be used to save memory. It will probably not work out of the box with
65
+ applications that open sockets or perform random I/O on files.
66
+ Databases like TokyoCabinet use concurrency-safe pread()/pwrite()
67
+ functions for safe sharing of database file descriptors across
68
+ processes.
69
+
70
+ * On POSIX-compliant filesystems, it is safe for multiple threads or
71
+ processes to append to one log file as long as all the processes are
72
+ have them unbuffered (File#sync = true) or they are
73
+ record(line)-buffered in userspace before any writes.
74
+
75
+ == Kernel Parameters (Linux sysctl and sysfs)
76
+
77
+ WARNING: Do not change system parameters unless you know what you're doing!
78
+
79
+ * Transparent hugepages (THP) improves performance in many cases,
80
+ but can also increase memory use when relying on a
81
+ copy-on-write(CoW)-friendly GC (Ruby 2.0+) with "preload_app true".
82
+ CoW operates at the page level, so writing to a huge page would
83
+ trigger a 2 MB copy (x86-64), as opposed to a 4 KB copy on a
84
+ regular (non-huge) page.
85
+
86
+ Consider only allowing THP to be used when it is requested via the
87
+ madvise(2) syscall:
88
+
89
+ echo madvise >/sys/kernel/mm/transparent_hugepage/enabled
90
+
91
+ Or disabling it system-wide, via "never".
92
+
93
+ n.b. "page" in this context only applies to the OS kernel,
94
+ Ruby GC implementations also use this term for the same concept
95
+ in a way that is agnostic to the OS.
96
+
97
+ * net.core.rmem_max and net.core.wmem_max can increase the allowed
98
+ size of :rcvbuf and :sndbuf respectively. This is mostly only useful
99
+ for UNIX domain sockets which do not have auto-tuning buffer sizes.
100
+
101
+ * For load testing/benchmarking with UNIX domain sockets, you should
102
+ consider increasing net.core.somaxconn or else nginx will start
103
+ failing to connect under heavy load. You may also consider setting
104
+ a higher :backlog to listen on as noted earlier.
105
+
106
+ * If you're running out of local ports, consider lowering
107
+ net.ipv4.tcp_fin_timeout to 20-30 (default: 60 seconds). Also
108
+ consider widening the usable port range by changing
109
+ net.ipv4.ip_local_port_range.
110
+
111
+ * Setting net.ipv4.tcp_timestamps=1 will also allow setting
112
+ net.ipv4.tcp_tw_reuse=1 and net.ipv4.tcp_tw_recycle=1, which along
113
+ with the above settings can slow down port exhaustion. Not all
114
+ networks are compatible with these settings, check with your friendly
115
+ network administrator before changing these.
116
+
117
+ * Increasing the MTU size can reduce framing overhead for larger
118
+ transfers. One often-overlooked detail is that the loopback
119
+ device (usually "lo") can have its MTU increased, too.
@@ -0,0 +1,3 @@
1
+ /data
2
+ /news
3
+ /requests
@@ -0,0 +1,4 @@
1
+ # group_name max expire headers_only
2
+ gmane.comp.lang.ruby.unicorn.general 1000000000 1000000000 0
3
+
4
+ # usage: slrnpull -d $PWD -h news.gmane.io --no-post
data/bin/unicorn ADDED
@@ -0,0 +1,129 @@
1
+ #!/this/will/be/overwritten/or/wrapped/anyways/do/not/worry/ruby
2
+ # -*- encoding: binary -*-
3
+ # frozen_string_literal: false
4
+ require 'unicorn/launcher'
5
+ require 'optparse'
6
+
7
+ ENV["RACK_ENV"] ||= "development"
8
+ rackup_opts = Unicorn::Configurator::RACKUP
9
+ options = rackup_opts[:options]
10
+ set_no_default_middleware = true
11
+
12
+ op = OptionParser.new("", 24, ' ') do |opts|
13
+ cmd = File.basename($0)
14
+ opts.banner = "Usage: #{cmd} " \
15
+ "[ruby options] [#{cmd} options] [rackup config file]"
16
+ opts.separator "Ruby options:"
17
+
18
+ lineno = 1
19
+ opts.on("-e", "--eval LINE", "evaluate a LINE of code") do |line|
20
+ eval line, TOPLEVEL_BINDING, "-e", lineno
21
+ lineno += 1
22
+ end
23
+
24
+ opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") do
25
+ $DEBUG = true
26
+ end
27
+
28
+ opts.on("-w", "--warn", "turn warnings on for your script") do
29
+ $-w = true
30
+ end
31
+
32
+ opts.on("-I", "--include PATH",
33
+ "specify $LOAD_PATH (may be used more than once)") do |path|
34
+ $LOAD_PATH.unshift(*path.split(':'))
35
+ end
36
+
37
+ opts.on("-r", "--require LIBRARY",
38
+ "require the library, before executing your script") do |library|
39
+ require library
40
+ end
41
+
42
+ opts.separator "#{cmd} options:"
43
+
44
+ # some of these switches exist for rackup command-line compatibility,
45
+
46
+ opts.on("-o", "--host HOST",
47
+ "listen on HOST (default: #{Unicorn::Const::DEFAULT_HOST})") do |h|
48
+ rackup_opts[:host] = h
49
+ rackup_opts[:set_listener] = true
50
+ end
51
+
52
+ opts.on("-p", "--port PORT", Integer,
53
+ "use PORT (default: #{Unicorn::Const::DEFAULT_PORT})") do |port|
54
+ rackup_opts[:port] = port
55
+ rackup_opts[:set_listener] = true
56
+ end
57
+
58
+ opts.on("-E", "--env RACK_ENV",
59
+ "use RACK_ENV for defaults (default: development)") do |e|
60
+ ENV["RACK_ENV"] = e
61
+ end
62
+
63
+ opts.on("-N", "--no-default-middleware",
64
+ "do not load middleware implied by RACK_ENV") do |e|
65
+ rackup_opts[:no_default_middleware] = true if set_no_default_middleware
66
+ end
67
+
68
+ opts.on("-D", "--daemonize", "run daemonized in the background") do |d|
69
+ rackup_opts[:daemonize] = !!d
70
+ end
71
+
72
+ opts.on("-P", "--pid FILE", "DEPRECATED") do |f|
73
+ warn %q{Use of --pid/-P is strongly discouraged}
74
+ warn %q{Use the 'pid' directive in the Unicorn config file instead}
75
+ options[:pid] = f
76
+ end
77
+
78
+ opts.on("-s", "--server SERVER",
79
+ "this flag only exists for compatibility") do |s|
80
+ warn "-s/--server only exists for compatibility with rackup"
81
+ end
82
+
83
+ # Unicorn-specific stuff
84
+ opts.on("-l", "--listen {HOST:PORT|PATH}",
85
+ "listen on HOST:PORT or PATH",
86
+ "this may be specified multiple times",
87
+ "(default: #{Unicorn::Const::DEFAULT_LISTEN})") do |address|
88
+ options[:listeners] << address
89
+ end
90
+
91
+ opts.on("-c", "--config-file FILE", "Unicorn-specific config file") do |f|
92
+ options[:config_file] = f
93
+ end
94
+
95
+ # I'm avoiding Unicorn-specific config options on the command-line.
96
+ # IMNSHO, config options on the command-line are redundant given
97
+ # config files and make things unnecessarily complicated with multiple
98
+ # places to look for a config option.
99
+
100
+ opts.separator "Common options:"
101
+
102
+ opts.on_tail("-h", "--help", "Show this message") do
103
+ puts opts.to_s.gsub(/^.*DEPRECATED.*$/s, '')
104
+ exit
105
+ end
106
+
107
+ opts.on_tail("-v", "--version", "Show version") do
108
+ puts "#{cmd} v#{Unicorn::Const::UNICORN_VERSION}"
109
+ exit
110
+ end
111
+
112
+ opts.parse! ARGV
113
+ end
114
+
115
+ set_no_default_middleware = false
116
+ app = Unicorn.builder(ARGV[0] || 'config.ru', op)
117
+ op = nil
118
+
119
+ if $DEBUG
120
+ require 'pp'
121
+ pp({
122
+ :unicorn_options => options,
123
+ :app => app,
124
+ :daemonize => rackup_opts[:daemonize],
125
+ })
126
+ end
127
+
128
+ Unicorn::Launcher.daemonize!(options) if rackup_opts[:daemonize]
129
+ Unicorn::HttpServer.new(app, options).start.join
data/bin/unicorn_rails ADDED
@@ -0,0 +1,210 @@
1
+ #!/this/will/be/overwritten/or/wrapped/anyways/do/not/worry/ruby
2
+ # -*- encoding: binary -*-
3
+ # frozen_string_literal: false
4
+ require 'unicorn/launcher'
5
+ require 'optparse'
6
+ require 'fileutils'
7
+
8
+ ENV['RAILS_ENV'] ||= "development"
9
+ rackup_opts = Unicorn::Configurator::RACKUP
10
+ options = rackup_opts[:options]
11
+
12
+ op = OptionParser.new("", 24, ' ') do |opts|
13
+ cmd = File.basename($0)
14
+ opts.banner = "Usage: #{cmd} " \
15
+ "[ruby options] [#{cmd} options] [rackup config file]"
16
+ opts.separator "Ruby options:"
17
+
18
+ lineno = 1
19
+ opts.on("-e", "--eval LINE", "evaluate a LINE of code") do |line|
20
+ eval line, TOPLEVEL_BINDING, "-e", lineno
21
+ lineno += 1
22
+ end
23
+
24
+ opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") do
25
+ $DEBUG = true
26
+ end
27
+
28
+ opts.on("-w", "--warn", "turn warnings on for your script") do
29
+ $-w = true
30
+ end
31
+
32
+ opts.on("-I", "--include PATH",
33
+ "specify $LOAD_PATH (may be used more than once)") do |path|
34
+ $LOAD_PATH.unshift(*path.split(':'))
35
+ end
36
+
37
+ opts.on("-r", "--require LIBRARY",
38
+ "require the library, before executing your script") do |library|
39
+ require library
40
+ end
41
+
42
+ opts.separator "#{cmd} options:"
43
+
44
+ # some of these switches exist for rackup command-line compatibility,
45
+
46
+ opts.on("-o", "--host HOST",
47
+ "listen on HOST (default: #{Unicorn::Const::DEFAULT_HOST})") do |h|
48
+ rackup_opts[:host] = h
49
+ rackup_opts[:set_listener] = true
50
+ end
51
+
52
+ opts.on("-p", "--port PORT", Integer,
53
+ "use PORT (default: #{Unicorn::Const::DEFAULT_PORT})") do |port|
54
+ rackup_opts[:port] = port
55
+ rackup_opts[:set_listener] = true
56
+ end
57
+
58
+ opts.on("-E", "--env RAILS_ENV",
59
+ "use RAILS_ENV for defaults (default: development)") do |e|
60
+ ENV['RAILS_ENV'] = e
61
+ end
62
+
63
+ opts.on("-D", "--daemonize", "run daemonized in the background") do |d|
64
+ rackup_opts[:daemonize] = !!d
65
+ end
66
+
67
+ # Unicorn-specific stuff
68
+ opts.on("-l", "--listen {HOST:PORT|PATH}",
69
+ "listen on HOST:PORT or PATH",
70
+ "this may be specified multiple times",
71
+ "(default: #{Unicorn::Const::DEFAULT_LISTEN})") do |address|
72
+ options[:listeners] << address
73
+ end
74
+
75
+ opts.on("-c", "--config-file FILE", "Unicorn-specific config file") do |f|
76
+ options[:config_file] = f
77
+ end
78
+
79
+ opts.on("-P PATH", "DEPRECATED") do |v|
80
+ warn %q{Use of -P is ambiguous and discouraged}
81
+ warn %q{Use --path or RAILS_RELATIVE_URL_ROOT instead}
82
+ ENV['RAILS_RELATIVE_URL_ROOT'] = v
83
+ end
84
+
85
+ opts.on("--path PATH", "Runs Rails app mounted at a specific path.",
86
+ "(default: /)") do |v|
87
+ ENV['RAILS_RELATIVE_URL_ROOT'] = v
88
+ end
89
+
90
+ # I'm avoiding Unicorn-specific config options on the command-line.
91
+ # IMNSHO, config options on the command-line are redundant given
92
+ # config files and make things unnecessarily complicated with multiple
93
+ # places to look for a config option.
94
+
95
+ opts.separator "Common options:"
96
+
97
+ opts.on_tail("-h", "--help", "Show this message") do
98
+ puts opts.to_s.gsub(/^.*DEPRECATED.*$/s, '')
99
+ exit
100
+ end
101
+
102
+ opts.on_tail("-v", "--version", "Show version") do
103
+ puts "#{cmd} v#{Unicorn::Const::UNICORN_VERSION}"
104
+ exit
105
+ end
106
+
107
+ opts.parse! ARGV
108
+ end
109
+
110
+ def rails_dispatcher
111
+ if ::Rails::VERSION::MAJOR >= 3 && ::File.exist?('config/application.rb')
112
+ if ::File.read('config/application.rb') =~ /^module\s+([\w:]+)\s*$/
113
+ app_module = Object.const_get($1)
114
+ begin
115
+ result = app_module::Application
116
+ rescue NameError
117
+ end
118
+ end
119
+ end
120
+
121
+ if result.nil? && defined?(ActionController::Dispatcher)
122
+ result = ActionController::Dispatcher.new
123
+ end
124
+
125
+ result || abort("Unable to locate the application dispatcher class")
126
+ end
127
+
128
+ def rails_builder(ru, op, daemonize)
129
+ return Unicorn.builder(ru, op) if ru
130
+
131
+ # allow Configurator to parse cli switches embedded in the ru file
132
+ Unicorn::Configurator::RACKUP.update(:file => :rails, :optparse => op)
133
+
134
+ # this lambda won't run until after forking if preload_app is false
135
+ # this runs after config file reloading
136
+ lambda do |x, server|
137
+ # Rails 3 includes a config.ru, use it if we find it after
138
+ # working_directory is bound.
139
+ ::File.exist?('config.ru') and
140
+ return Unicorn.builder('config.ru', op).call(x, server)
141
+
142
+ # Load Rails and (possibly) the private version of Rack it bundles.
143
+ begin
144
+ require ::File.expand_path('config/boot')
145
+ require ::File.expand_path('config/environment')
146
+ rescue LoadError => err
147
+ abort "#$0 must be run inside RAILS_ROOT: #{err.inspect}"
148
+ end
149
+
150
+ defined?(::Rails::VERSION::STRING) or
151
+ abort "Rails::VERSION::STRING not defined by config/{boot,environment}"
152
+ # it seems Rails >=2.2 support Rack, but only >=2.3 requires it
153
+ old_rails = case ::Rails::VERSION::MAJOR
154
+ when 0, 1 then true
155
+ when 2 then Rails::VERSION::MINOR < 3 ? true : false
156
+ else
157
+ false
158
+ end
159
+
160
+ Rack::Builder.new do
161
+ map_path = ENV['RAILS_RELATIVE_URL_ROOT'] || '/'
162
+ if old_rails
163
+ if map_path != '/'
164
+ # patches + tests welcome, but I really cbf to deal with this
165
+ # since all apps I've ever dealt with just use "/" ...
166
+ warn "relative URL roots may not work for older Rails"
167
+ end
168
+ warn "LogTailer not available for Rails < 2.3" unless daemonize
169
+ warn "Debugger not available" if $DEBUG
170
+ require 'unicorn/app/old_rails'
171
+ map(map_path) do
172
+ use Unicorn::App::OldRails::Static
173
+ run Unicorn::App::OldRails.new
174
+ end
175
+ else
176
+ use Rails::Rack::LogTailer unless daemonize
177
+ use Rails::Rack::Debugger if $DEBUG
178
+ map(map_path) do
179
+ unless defined?(ActionDispatch::Static)
180
+ use Rails::Rack::Static
181
+ end
182
+ run rails_dispatcher
183
+ end
184
+ end
185
+ end.to_app
186
+ end
187
+ end
188
+
189
+ app = rails_builder(ARGV[0], op, rackup_opts[:daemonize])
190
+ op = nil
191
+
192
+ if $DEBUG
193
+ require 'pp'
194
+ pp({
195
+ :unicorn_options => options,
196
+ :app => app,
197
+ :daemonize => rackup_opts[:daemonize],
198
+ })
199
+ end
200
+
201
+ # ensure Rails standard tmp paths exist
202
+ options[:after_reload] = lambda do
203
+ FileUtils.mkdir_p(%w(cache pids sessions sockets).map! { |d| "tmp/#{d}" })
204
+ end
205
+
206
+ if rackup_opts[:daemonize]
207
+ options[:pid] = "tmp/pids/unicorn.pid"
208
+ Unicorn::Launcher.daemonize!(options)
209
+ end
210
+ Unicorn::HttpServer.new(app, options).start.join
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: false
2
+ # see {Unicorn::OobGC}[https://yhbt.net/unicorn/Unicorn/OobGC.html]
3
+ # Unicorn::OobGC was broken in Unicorn v3.3.1 - v3.6.1 and fixed in v3.6.2
data/examples/echo.ru ADDED
@@ -0,0 +1,27 @@
1
+ #\-E none
2
+ # frozen_string_literal: false
3
+ #
4
+ # Example application that echoes read data back to the HTTP client.
5
+ # This emulates the old echo protocol people used to run.
6
+ #
7
+ # An example of using this in a client would be to run:
8
+ # curl --no-buffer -T- http://host:port/
9
+ #
10
+ # Then type random stuff in your terminal to watch it get echoed back!
11
+
12
+ class EchoBody < Struct.new(:input)
13
+
14
+ def each(&block)
15
+ while buf = input.read(4096)
16
+ yield buf
17
+ end
18
+ self
19
+ end
20
+
21
+ end
22
+
23
+ run lambda { |env|
24
+ /\A100-continue\z/i =~ env['HTTP_EXPECT'] and return [100, {}, []]
25
+ [ 200, { 'Content-Type' => 'application/octet-stream' },
26
+ EchoBody.new(env['rack.input']) ]
27
+ }
data/examples/init.sh ADDED
@@ -0,0 +1,102 @@
1
+ #!/bin/sh
2
+ set -e
3
+ ### BEGIN INIT INFO
4
+ # Provides: unicorn
5
+ # Required-Start: $local_fs $network
6
+ # Required-Stop: $local_fs $network
7
+ # Default-Start: 2 3 4 5
8
+ # Default-Stop: 0 1 6
9
+ # Short-Description: Start/stop unicorn Rack app server
10
+ ### END INIT INFO
11
+
12
+ # Example init script, this can be used with nginx, too,
13
+ # since nginx and unicorn accept the same signals.
14
+
15
+ # Feel free to change any of the following variables for your app:
16
+ TIMEOUT=${TIMEOUT-60}
17
+ APP_ROOT=/home/x/my_app/current
18
+ PID=$APP_ROOT/tmp/pids/unicorn.pid
19
+ CMD="/usr/bin/unicorn -D -c $APP_ROOT/config/unicorn.rb"
20
+ INIT_CONF=$APP_ROOT/config/init.conf
21
+ UPGRADE_DELAY=${UPGRADE_DELAY-2}
22
+ action="$1"
23
+ set -u
24
+
25
+ test -f "$INIT_CONF" && . $INIT_CONF
26
+
27
+ OLD="$PID.oldbin"
28
+
29
+ cd $APP_ROOT || exit 1
30
+
31
+ sig () {
32
+ test -s "$PID" && kill -$1 $(cat $PID)
33
+ }
34
+
35
+ oldsig () {
36
+ test -s "$OLD" && kill -$1 $(cat $OLD)
37
+ }
38
+
39
+ case $action in
40
+ start)
41
+ sig 0 && echo >&2 "Already running" && exit 0
42
+ $CMD
43
+ ;;
44
+ stop)
45
+ sig QUIT && exit 0
46
+ echo >&2 "Not running"
47
+ ;;
48
+ force-stop)
49
+ sig TERM && exit 0
50
+ echo >&2 "Not running"
51
+ ;;
52
+ restart|reload)
53
+ sig HUP && echo reloaded OK && exit 0
54
+ echo >&2 "Couldn't reload, starting '$CMD' instead"
55
+ $CMD
56
+ ;;
57
+ upgrade)
58
+ if oldsig 0
59
+ then
60
+ echo >&2 "Old upgraded process still running with $OLD"
61
+ exit 1
62
+ fi
63
+
64
+ cur_pid=
65
+ if test -s "$PID"
66
+ then
67
+ cur_pid=$(cat $PID)
68
+ fi
69
+
70
+ if test -n "$cur_pid" &&
71
+ kill -USR2 "$cur_pid" &&
72
+ sleep $UPGRADE_DELAY &&
73
+ new_pid=$(cat $PID) &&
74
+ test x"$new_pid" != x"$cur_pid" &&
75
+ kill -0 "$new_pid" &&
76
+ kill -QUIT "$cur_pid"
77
+ then
78
+ n=$TIMEOUT
79
+ while kill -0 "$cur_pid" 2>/dev/null && test $n -ge 0
80
+ do
81
+ printf '.' && sleep 1 && n=$(( $n - 1 ))
82
+ done
83
+ echo
84
+
85
+ if test $n -lt 0 && kill -0 "$cur_pid" 2>/dev/null
86
+ then
87
+ echo >&2 "$cur_pid still running after $TIMEOUT seconds"
88
+ exit 1
89
+ fi
90
+ exit 0
91
+ fi
92
+ echo >&2 "Couldn't upgrade, starting '$CMD' instead"
93
+ $CMD
94
+ ;;
95
+ reopen-logs)
96
+ sig USR1
97
+ ;;
98
+ *)
99
+ echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>"
100
+ exit 1
101
+ ;;
102
+ esac
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: false
2
+ # Multi-Processing-safe monkey patch for Logger
3
+ #
4
+ # This monkey patch fixes the case where "preload_app true" is used and
5
+ # the application spawns a background thread upon being loaded.
6
+ #
7
+ # This removes all lock from the Logger code and solely relies on the
8
+ # underlying filesystem to handle write(2) system calls atomically when
9
+ # O_APPEND is used. This is safe in the presence of both multiple
10
+ # threads (native or green) and multiple processes when writing to
11
+ # a filesystem with POSIX O_APPEND semantics.
12
+ #
13
+ # It should be noted that the original locking on Logger could _never_ be
14
+ # considered reliable on non-POSIX filesystems with multiple processes,
15
+ # either, so nothing is lost in that case.
16
+
17
+ require 'logger'
18
+ class Logger::LogDevice
19
+ def write(message)
20
+ @dev.syswrite(message)
21
+ end
22
+
23
+ def close
24
+ @dev.close
25
+ end
26
+ end
@@ -0,0 +1,44 @@
1
+ # example logrotate config file, I usually keep this in
2
+ # /etc/logrotate.d/unicorn_app on my Debian systems
3
+ #
4
+ # See the logrotate(8) manpage for more information:
5
+ # https://linux.die.net/man/8/logrotate
6
+ #
7
+ # public logrotate-related discussion in our archives:
8
+ # https://yhbt.net/unicorn-public/?q=logrotate
9
+
10
+ # Modify the following glob to match the logfiles your app writes to:
11
+ /var/log/unicorn_app/*.log {
12
+ # this first block is mostly just personal preference, though
13
+ # I wish logrotate offered an "hourly" option...
14
+ daily
15
+ missingok
16
+ rotate 180
17
+ compress # must use with delaycompress below
18
+ dateext
19
+
20
+ # this is important if using "compress" since we need to call
21
+ # the "lastaction" script below before compressing:
22
+ delaycompress
23
+
24
+ # note the lack of the evil "copytruncate" option in this
25
+ # config. Unicorn supports the USR1 signal and we send it
26
+ # as our "lastaction" action:
27
+ lastaction
28
+ # For systemd users, assuming you use two services
29
+ # (as recommended) to allow zero-downtime upgrades.
30
+ # Only one service needs to be started, but signaling
31
+ # both here is harmless as long as they're both enabled
32
+ systemctl kill -s SIGUSR1 unicorn@1.service
33
+ systemctl kill -s SIGUSR1 unicorn@2.service
34
+
35
+ # Examples for other process management systems appreciated
36
+ # Mail us at unicorn-public@yhbt.net
37
+ # (see above for archives)
38
+
39
+ # If you use a pid file and assuming your pid file
40
+ # is in /var/run/unicorn_app/pid
41
+ pid=/var/run/unicorn_app/pid
42
+ test -s $pid && kill -USR1 "$(cat $pid)"
43
+ endscript
44
+ }