puma 4.1.1 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.md +149 -10
- data/LICENSE +23 -20
- data/README.md +30 -46
- data/docs/architecture.md +3 -3
- data/docs/deployment.md +9 -3
- data/docs/fork_worker.md +31 -0
- data/docs/jungle/README.md +13 -0
- data/{tools → docs}/jungle/rc.d/README.md +0 -0
- data/{tools → docs}/jungle/rc.d/puma +0 -0
- data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
- data/{tools → docs}/jungle/upstart/README.md +0 -0
- data/{tools → docs}/jungle/upstart/puma-manager.conf +0 -0
- data/{tools → docs}/jungle/upstart/puma.conf +0 -0
- data/docs/plugins.md +20 -10
- data/docs/signals.md +7 -6
- data/docs/systemd.md +1 -63
- data/ext/puma_http11/PumaHttp11Service.java +2 -4
- data/ext/puma_http11/extconf.rb +6 -0
- data/ext/puma_http11/http11_parser.c +40 -63
- data/ext/puma_http11/http11_parser.java.rl +21 -37
- data/ext/puma_http11/http11_parser.rl +3 -1
- data/ext/puma_http11/http11_parser_common.rl +3 -3
- data/ext/puma_http11/mini_ssl.c +15 -2
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +108 -116
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +91 -106
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +77 -18
- data/ext/puma_http11/puma_http11.c +9 -38
- data/lib/puma.rb +23 -0
- data/lib/puma/app/status.rb +46 -30
- data/lib/puma/binder.rb +112 -124
- data/lib/puma/cli.rb +11 -15
- data/lib/puma/client.rb +250 -209
- data/lib/puma/cluster.rb +203 -85
- data/lib/puma/commonlogger.rb +2 -2
- data/lib/puma/configuration.rb +31 -42
- data/lib/puma/const.rb +24 -19
- data/lib/puma/control_cli.rb +46 -17
- data/lib/puma/detect.rb +17 -0
- data/lib/puma/dsl.rb +162 -70
- data/lib/puma/error_logger.rb +97 -0
- data/lib/puma/events.rb +35 -31
- data/lib/puma/io_buffer.rb +9 -2
- data/lib/puma/jruby_restart.rb +0 -58
- data/lib/puma/launcher.rb +117 -58
- data/lib/puma/minissl.rb +60 -18
- data/lib/puma/minissl/context_builder.rb +73 -0
- data/lib/puma/null_io.rb +1 -1
- data/lib/puma/plugin.rb +6 -12
- data/lib/puma/rack/builder.rb +0 -4
- data/lib/puma/reactor.rb +16 -9
- data/lib/puma/runner.rb +11 -32
- data/lib/puma/server.rb +173 -193
- data/lib/puma/single.rb +7 -64
- data/lib/puma/state_file.rb +6 -3
- data/lib/puma/thread_pool.rb +104 -81
- data/lib/rack/handler/puma.rb +1 -5
- data/tools/Dockerfile +16 -0
- data/tools/trickletest.rb +0 -1
- metadata +23 -24
- data/ext/puma_http11/io_buffer.c +0 -155
- data/ext/puma_http11/org/jruby/puma/IOBuffer.java +0 -72
- data/lib/puma/convenient.rb +0 -25
- data/lib/puma/daemon_ext.rb +0 -33
- data/lib/puma/delegation.rb +0 -13
- data/lib/puma/tcp_logger.rb +0 -41
- data/tools/jungle/README.md +0 -19
- data/tools/jungle/init.d/README.md +0 -61
- data/tools/jungle/init.d/puma +0 -421
- data/tools/jungle/init.d/run-puma +0 -18
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'puma/const'
|
4
|
+
|
5
|
+
module Puma
|
6
|
+
# The implementation of a detailed error logging.
|
7
|
+
# @version 5.0.0
|
8
|
+
#
|
9
|
+
class ErrorLogger
|
10
|
+
include Const
|
11
|
+
|
12
|
+
attr_reader :ioerr
|
13
|
+
|
14
|
+
REQUEST_FORMAT = %{"%s %s%s" - (%s)}
|
15
|
+
|
16
|
+
def initialize(ioerr)
|
17
|
+
@ioerr = ioerr
|
18
|
+
@ioerr.sync = true
|
19
|
+
|
20
|
+
@debug = ENV.key? 'PUMA_DEBUG'
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.stdio
|
24
|
+
new $stderr
|
25
|
+
end
|
26
|
+
|
27
|
+
# Print occured error details.
|
28
|
+
# +options+ hash with additional options:
|
29
|
+
# - +error+ is an exception object
|
30
|
+
# - +req+ the http request
|
31
|
+
# - +text+ (default nil) custom string to print in title
|
32
|
+
# and before all remaining info.
|
33
|
+
#
|
34
|
+
def info(options={})
|
35
|
+
ioerr.puts title(options)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Print occured error details only if
|
39
|
+
# environment variable PUMA_DEBUG is defined.
|
40
|
+
# +options+ hash with additional options:
|
41
|
+
# - +error+ is an exception object
|
42
|
+
# - +req+ the http request
|
43
|
+
# - +text+ (default nil) custom string to print in title
|
44
|
+
# and before all remaining info.
|
45
|
+
#
|
46
|
+
def debug(options={})
|
47
|
+
return unless @debug
|
48
|
+
|
49
|
+
error = options[:error]
|
50
|
+
req = options[:req]
|
51
|
+
|
52
|
+
string_block = []
|
53
|
+
string_block << title(options)
|
54
|
+
string_block << request_dump(req) if req
|
55
|
+
string_block << error_backtrace(options) if error
|
56
|
+
|
57
|
+
ioerr.puts string_block.join("\n")
|
58
|
+
end
|
59
|
+
|
60
|
+
def title(options={})
|
61
|
+
text = options[:text]
|
62
|
+
req = options[:req]
|
63
|
+
error = options[:error]
|
64
|
+
|
65
|
+
string_block = ["#{Time.now}"]
|
66
|
+
string_block << " #{text}" if text
|
67
|
+
string_block << " (#{request_title(req)})" if request_parsed?(req)
|
68
|
+
string_block << ": #{error.inspect}" if error
|
69
|
+
string_block.join('')
|
70
|
+
end
|
71
|
+
|
72
|
+
def request_dump(req)
|
73
|
+
"Headers: #{request_headers(req)}\n" \
|
74
|
+
"Body: #{req.body}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def request_title(req)
|
78
|
+
env = req.env
|
79
|
+
|
80
|
+
REQUEST_FORMAT % [
|
81
|
+
env[REQUEST_METHOD],
|
82
|
+
env[REQUEST_PATH] || env[PATH_INFO],
|
83
|
+
env[QUERY_STRING] || "",
|
84
|
+
env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR] || "-"
|
85
|
+
]
|
86
|
+
end
|
87
|
+
|
88
|
+
def request_headers(req)
|
89
|
+
headers = req.env.select { |key, _| key.start_with?('HTTP_') }
|
90
|
+
headers.map { |key, value| [key[5..-1], value] }.to_h.inspect
|
91
|
+
end
|
92
|
+
|
93
|
+
def request_parsed?(req)
|
94
|
+
req && req.env[REQUEST_METHOD]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/puma/events.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'puma/const'
|
4
3
|
require "puma/null_io"
|
4
|
+
require 'puma/error_logger'
|
5
5
|
require 'stringio'
|
6
6
|
|
7
7
|
module Puma
|
@@ -23,8 +23,6 @@ module Puma
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
include Const
|
27
|
-
|
28
26
|
# Create an Events object that prints to +stdout+ and +stderr+.
|
29
27
|
#
|
30
28
|
def initialize(stdout, stderr)
|
@@ -36,6 +34,7 @@ module Puma
|
|
36
34
|
@stderr.sync = true
|
37
35
|
|
38
36
|
@debug = ENV.key? 'PUMA_DEBUG'
|
37
|
+
@error_logger = ErrorLogger.new(@stderr)
|
39
38
|
|
40
39
|
@hooks = Hash.new { |h,k| h[k] = [] }
|
41
40
|
end
|
@@ -66,7 +65,8 @@ module Puma
|
|
66
65
|
# Write +str+ to +@stdout+
|
67
66
|
#
|
68
67
|
def log(str)
|
69
|
-
@stdout.puts format(str)
|
68
|
+
@stdout.puts format(str) if @stdout.respond_to? :puts
|
69
|
+
rescue Errno::EPIPE
|
70
70
|
end
|
71
71
|
|
72
72
|
def write(str)
|
@@ -80,7 +80,7 @@ module Puma
|
|
80
80
|
# Write +str+ to +@stderr+
|
81
81
|
#
|
82
82
|
def error(str)
|
83
|
-
@
|
83
|
+
@error_logger.info(text: format("ERROR: #{str}"))
|
84
84
|
exit 1
|
85
85
|
end
|
86
86
|
|
@@ -88,43 +88,47 @@ module Puma
|
|
88
88
|
formatter.call(str)
|
89
89
|
end
|
90
90
|
|
91
|
+
# An HTTP connection error has occurred.
|
92
|
+
# +error+ a connection exception, +req+ the request,
|
93
|
+
# and +text+ additional info
|
94
|
+
# @version 5.0.0
|
95
|
+
#
|
96
|
+
def connection_error(error, req, text="HTTP connection error")
|
97
|
+
@error_logger.info(error: error, req: req, text: text)
|
98
|
+
end
|
99
|
+
|
91
100
|
# An HTTP parse error has occurred.
|
92
|
-
# +
|
93
|
-
#
|
101
|
+
# +error+ a parsing exception,
|
102
|
+
# and +req+ the request.
|
94
103
|
#
|
95
|
-
def parse_error(
|
96
|
-
@
|
97
|
-
"(#{env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR]}#{env[REQUEST_PATH]}): " \
|
98
|
-
"#{error.inspect}" \
|
99
|
-
"\n---\n"
|
104
|
+
def parse_error(error, req)
|
105
|
+
@error_logger.info(error: error, req: req, text: 'HTTP parse error, malformed request')
|
100
106
|
end
|
101
107
|
|
102
108
|
# An SSL error has occurred.
|
103
|
-
# +
|
104
|
-
# any peer certificate (if present)
|
109
|
+
# +error+ an exception object, +peeraddr+ peer address,
|
110
|
+
# and +peercert+ any peer certificate (if present).
|
105
111
|
#
|
106
|
-
def ssl_error(
|
112
|
+
def ssl_error(error, peeraddr, peercert)
|
107
113
|
subject = peercert ? peercert.subject : nil
|
108
|
-
@
|
114
|
+
@error_logger.info(error: error, text: "SSL error, peer: #{peeraddr}, peer cert: #{subject}")
|
109
115
|
end
|
110
116
|
|
111
117
|
# An unknown error has occurred.
|
112
|
-
# +
|
113
|
-
# +
|
118
|
+
# +error+ an exception object, +req+ the request,
|
119
|
+
# and +text+ additional info
|
114
120
|
#
|
115
|
-
def unknown_error(
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
@stderr.puts string_block.join("\n")
|
127
|
-
end
|
121
|
+
def unknown_error(error, req=nil, text="Unknown error")
|
122
|
+
@error_logger.info(error: error, req: req, text: text)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Log occurred error debug dump.
|
126
|
+
# +error+ an exception object, +req+ the request,
|
127
|
+
# and +text+ additional info
|
128
|
+
# @version 5.0.0
|
129
|
+
#
|
130
|
+
def debug_error(error, req=nil, text="")
|
131
|
+
@error_logger.debug(error: error, req: req, text: text)
|
128
132
|
end
|
129
133
|
|
130
134
|
def on_booted(&block)
|
data/lib/puma/io_buffer.rb
CHANGED
data/lib/puma/jruby_restart.rb
CHANGED
@@ -22,63 +22,5 @@ module Puma
|
|
22
22
|
execlp(cmd, *argv)
|
23
23
|
raise SystemCallError.new(FFI.errno)
|
24
24
|
end
|
25
|
-
|
26
|
-
PermKey = 'PUMA_DAEMON_PERM'
|
27
|
-
RestartKey = 'PUMA_DAEMON_RESTART'
|
28
|
-
|
29
|
-
# Called to tell things "Your now always in daemon mode,
|
30
|
-
# don't try to reenter it."
|
31
|
-
#
|
32
|
-
def self.perm_daemonize
|
33
|
-
ENV[PermKey] = "1"
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.daemon?
|
37
|
-
ENV.key?(PermKey) || ENV.key?(RestartKey)
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.daemon_init
|
41
|
-
return true if ENV.key?(PermKey)
|
42
|
-
|
43
|
-
return false unless ENV.key? RestartKey
|
44
|
-
|
45
|
-
master = ENV[RestartKey]
|
46
|
-
|
47
|
-
# In case the master disappears early
|
48
|
-
begin
|
49
|
-
Process.kill "SIGUSR2", master.to_i
|
50
|
-
rescue SystemCallError => e
|
51
|
-
end
|
52
|
-
|
53
|
-
ENV[RestartKey] = ""
|
54
|
-
|
55
|
-
setsid
|
56
|
-
|
57
|
-
null = File.open "/dev/null", "w+"
|
58
|
-
STDIN.reopen null
|
59
|
-
STDOUT.reopen null
|
60
|
-
STDERR.reopen null
|
61
|
-
|
62
|
-
true
|
63
|
-
end
|
64
|
-
|
65
|
-
def self.daemon_start(dir, argv)
|
66
|
-
ENV[RestartKey] = Process.pid.to_s
|
67
|
-
|
68
|
-
if k = ENV['PUMA_JRUBY_DAEMON_OPTS']
|
69
|
-
ENV['JRUBY_OPTS'] = k
|
70
|
-
end
|
71
|
-
|
72
|
-
cmd = argv.first
|
73
|
-
argv = ([:string] * argv.size).zip(argv).flatten
|
74
|
-
argv << :string
|
75
|
-
argv << nil
|
76
|
-
|
77
|
-
chdir(dir)
|
78
|
-
ret = fork
|
79
|
-
return ret if ret != 0
|
80
|
-
execlp(cmd, *argv)
|
81
|
-
raise SystemCallError.new(FFI.errno)
|
82
|
-
end
|
83
25
|
end
|
84
26
|
end
|
data/lib/puma/launcher.rb
CHANGED
@@ -2,12 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'puma/events'
|
4
4
|
require 'puma/detect'
|
5
|
-
|
6
5
|
require 'puma/cluster'
|
7
6
|
require 'puma/single'
|
8
|
-
|
9
7
|
require 'puma/const'
|
10
|
-
|
11
8
|
require 'puma/binder'
|
12
9
|
|
13
10
|
module Puma
|
@@ -50,8 +47,9 @@ module Puma
|
|
50
47
|
@original_argv = @argv.dup
|
51
48
|
@config = conf
|
52
49
|
|
53
|
-
@binder = Binder.new(@events)
|
54
|
-
@binder.
|
50
|
+
@binder = Binder.new(@events, conf)
|
51
|
+
@binder.create_inherited_fds(ENV).each { |k| ENV.delete k }
|
52
|
+
@binder.create_activated_fds(ENV).each { |k| ENV.delete k }
|
55
53
|
|
56
54
|
@environment = conf.environment
|
57
55
|
|
@@ -72,10 +70,6 @@ module Puma
|
|
72
70
|
unsupported "worker mode not supported on #{RUBY_ENGINE} on this platform"
|
73
71
|
end
|
74
72
|
|
75
|
-
if @options[:daemon] && Puma.windows?
|
76
|
-
unsupported 'daemon mode not supported on Windows'
|
77
|
-
end
|
78
|
-
|
79
73
|
Dir.chdir(@restart_dir)
|
80
74
|
|
81
75
|
prune_bundler if prune_bundler?
|
@@ -108,6 +102,7 @@ module Puma
|
|
108
102
|
write_pid
|
109
103
|
|
110
104
|
path = @options[:state]
|
105
|
+
permission = @options[:state_permission]
|
111
106
|
return unless path
|
112
107
|
|
113
108
|
require 'puma/state_file'
|
@@ -116,8 +111,9 @@ module Puma
|
|
116
111
|
sf.pid = Process.pid
|
117
112
|
sf.control_url = @options[:control_url]
|
118
113
|
sf.control_auth_token = @options[:control_auth_token]
|
114
|
+
sf.running_from = File.expand_path('.')
|
119
115
|
|
120
|
-
sf.save path
|
116
|
+
sf.save path, permission
|
121
117
|
end
|
122
118
|
|
123
119
|
# Delete the configured pidfile
|
@@ -126,19 +122,6 @@ module Puma
|
|
126
122
|
File.unlink(path) if path && File.exist?(path)
|
127
123
|
end
|
128
124
|
|
129
|
-
# If configured, write the pid of the current process out
|
130
|
-
# to a file.
|
131
|
-
def write_pid
|
132
|
-
path = @options[:pidfile]
|
133
|
-
return unless path
|
134
|
-
|
135
|
-
File.open(path, 'w') { |f| f.puts Process.pid }
|
136
|
-
cur = Process.pid
|
137
|
-
at_exit do
|
138
|
-
delete_pidfile if cur == Process.pid
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
125
|
# Begin async shutdown of the server
|
143
126
|
def halt
|
144
127
|
@status = :halt
|
@@ -190,21 +173,24 @@ module Puma
|
|
190
173
|
case @status
|
191
174
|
when :halt
|
192
175
|
log "* Stopping immediately!"
|
176
|
+
@runner.stop_control
|
193
177
|
when :run, :stop
|
194
178
|
graceful_stop
|
195
179
|
when :restart
|
196
180
|
log "* Restarting..."
|
197
181
|
ENV.replace(previous_env)
|
198
|
-
@runner.
|
182
|
+
@runner.stop_control
|
199
183
|
restart!
|
200
184
|
when :exit
|
201
185
|
# nothing
|
202
186
|
end
|
187
|
+
close_binder_listeners unless @status == :restart
|
203
188
|
end
|
204
189
|
|
205
|
-
# Return
|
206
|
-
|
207
|
-
|
190
|
+
# Return all tcp ports the launcher may be using, TCP or SSL
|
191
|
+
# @version 5.0.0
|
192
|
+
def connected_ports
|
193
|
+
@binder.connected_ports
|
208
194
|
end
|
209
195
|
|
210
196
|
def restart_args
|
@@ -217,22 +203,43 @@ module Puma
|
|
217
203
|
end
|
218
204
|
|
219
205
|
def close_binder_listeners
|
220
|
-
@
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
206
|
+
@runner.close_control_listeners
|
207
|
+
@binder.close_listeners
|
208
|
+
end
|
209
|
+
|
210
|
+
# @version 5.0.0
|
211
|
+
def thread_status
|
212
|
+
Thread.list.each do |thread|
|
213
|
+
name = "Thread: TID-#{thread.object_id.to_s(36)}"
|
214
|
+
name += " #{thread['label']}" if thread['label']
|
215
|
+
name += " #{thread.name}" if thread.respond_to?(:name) && thread.name
|
216
|
+
backtrace = thread.backtrace || ["<no backtrace available>"]
|
217
|
+
|
218
|
+
yield name, backtrace
|
225
219
|
end
|
226
220
|
end
|
227
221
|
|
228
222
|
private
|
229
223
|
|
224
|
+
# If configured, write the pid of the current process out
|
225
|
+
# to a file.
|
226
|
+
def write_pid
|
227
|
+
path = @options[:pidfile]
|
228
|
+
return unless path
|
229
|
+
|
230
|
+
File.open(path, 'w') { |f| f.puts Process.pid }
|
231
|
+
cur = Process.pid
|
232
|
+
at_exit do
|
233
|
+
delete_pidfile if cur == Process.pid
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
230
237
|
def reload_worker_directory
|
231
238
|
@runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
|
232
239
|
end
|
233
240
|
|
234
241
|
def restart!
|
235
|
-
@config.run_hooks :on_restart, self
|
242
|
+
@config.run_hooks :on_restart, self, @events
|
236
243
|
|
237
244
|
if Puma.jruby?
|
238
245
|
close_binder_listeners
|
@@ -246,48 +253,75 @@ module Puma
|
|
246
253
|
Dir.chdir(@restart_dir)
|
247
254
|
Kernel.exec(*argv)
|
248
255
|
else
|
249
|
-
redirects = {:close_others => true}
|
250
|
-
@binder.listeners.each_with_index do |(l, io), i|
|
251
|
-
ENV["PUMA_INHERIT_#{i}"] = "#{io.to_i}:#{l}"
|
252
|
-
redirects[io.to_i] = io.to_i
|
253
|
-
end
|
254
|
-
|
255
256
|
argv = restart_args
|
256
257
|
Dir.chdir(@restart_dir)
|
257
|
-
|
258
|
+
ENV.update(@binder.redirects_for_restart_env)
|
259
|
+
argv += [@binder.redirects_for_restart]
|
258
260
|
Kernel.exec(*argv)
|
259
261
|
end
|
260
262
|
end
|
261
263
|
|
262
|
-
def
|
263
|
-
|
264
|
-
|
265
|
-
|
264
|
+
def dependencies_and_files_to_require_after_prune
|
265
|
+
puma = spec_for_gem("puma")
|
266
|
+
|
267
|
+
deps = puma.runtime_dependencies.map do |d|
|
268
|
+
"#{d.name}:#{spec_for_gem(d.name).version}"
|
269
|
+
end
|
270
|
+
|
271
|
+
[deps, require_paths_for_gem(puma) + extra_runtime_deps_directories]
|
272
|
+
end
|
273
|
+
|
274
|
+
def extra_runtime_deps_directories
|
275
|
+
Array(@options[:extra_runtime_dependencies]).map do |d_name|
|
276
|
+
if (spec = spec_for_gem(d_name))
|
277
|
+
require_paths_for_gem(spec)
|
278
|
+
else
|
279
|
+
log "* Could not load extra dependency: #{d_name}"
|
280
|
+
nil
|
281
|
+
end
|
282
|
+
end.flatten.compact
|
283
|
+
end
|
284
|
+
|
285
|
+
def puma_wild_location
|
286
|
+
puma = spec_for_gem("puma")
|
287
|
+
dirs = require_paths_for_gem(puma)
|
266
288
|
puma_lib_dir = dirs.detect { |x| File.exist? File.join(x, '../bin/puma-wild') }
|
289
|
+
File.expand_path(File.join(puma_lib_dir, "../bin/puma-wild"))
|
290
|
+
end
|
267
291
|
|
268
|
-
|
292
|
+
def prune_bundler
|
293
|
+
return if ENV['PUMA_BUNDLER_PRUNED']
|
294
|
+
return unless defined?(Bundler)
|
295
|
+
require_rubygems_min_version!(Gem::Version.new("2.2"), "prune_bundler")
|
296
|
+
unless puma_wild_location
|
269
297
|
log "! Unable to prune Bundler environment, continuing"
|
270
298
|
return
|
271
299
|
end
|
272
300
|
|
273
|
-
deps =
|
274
|
-
spec = Bundler.rubygems.loaded_specs(d.name)
|
275
|
-
"#{d.name}:#{spec.version.to_s}"
|
276
|
-
end
|
301
|
+
deps, dirs = dependencies_and_files_to_require_after_prune
|
277
302
|
|
278
303
|
log '* Pruning Bundler environment'
|
279
304
|
home = ENV['GEM_HOME']
|
280
|
-
Bundler.
|
305
|
+
bundle_gemfile = Bundler.original_env['BUNDLE_GEMFILE']
|
306
|
+
with_unbundled_env do
|
281
307
|
ENV['GEM_HOME'] = home
|
308
|
+
ENV['BUNDLE_GEMFILE'] = bundle_gemfile
|
282
309
|
ENV['PUMA_BUNDLER_PRUNED'] = '1'
|
283
|
-
|
284
|
-
args = [Gem.ruby, wild, '-I', dirs.join(':'), deps.join(',')] + @original_argv
|
310
|
+
args = [Gem.ruby, puma_wild_location, '-I', dirs.join(':'), deps.join(',')] + @original_argv
|
285
311
|
# Ruby 2.0+ defaults to true which breaks socket activation
|
286
312
|
args += [{:close_others => false}]
|
287
313
|
Kernel.exec(*args)
|
288
314
|
end
|
289
315
|
end
|
290
316
|
|
317
|
+
def spec_for_gem(gem_name)
|
318
|
+
Bundler.rubygems.loaded_specs(gem_name)
|
319
|
+
end
|
320
|
+
|
321
|
+
def require_paths_for_gem(gem_spec)
|
322
|
+
gem_spec.full_require_paths
|
323
|
+
end
|
324
|
+
|
291
325
|
def log(str)
|
292
326
|
@events.log str
|
293
327
|
end
|
@@ -406,12 +440,6 @@ module Puma
|
|
406
440
|
|
407
441
|
begin
|
408
442
|
Signal.trap "SIGINT" do
|
409
|
-
if Puma.jruby?
|
410
|
-
@status = :exit
|
411
|
-
graceful_stop
|
412
|
-
exit
|
413
|
-
end
|
414
|
-
|
415
443
|
stop
|
416
444
|
end
|
417
445
|
rescue Exception
|
@@ -429,6 +457,37 @@ module Puma
|
|
429
457
|
rescue Exception
|
430
458
|
log "*** SIGHUP not implemented, signal based logs reopening unavailable!"
|
431
459
|
end
|
460
|
+
|
461
|
+
begin
|
462
|
+
unless Puma.jruby? # INFO in use by JVM already
|
463
|
+
Signal.trap "SIGINFO" do
|
464
|
+
thread_status do |name, backtrace|
|
465
|
+
@events.log name
|
466
|
+
@events.log backtrace.map { |bt| " #{bt}" }
|
467
|
+
end
|
468
|
+
end
|
469
|
+
end
|
470
|
+
rescue Exception
|
471
|
+
# Not going to log this one, as SIGINFO is *BSD only and would be pretty annoying
|
472
|
+
# to see this constantly on Linux.
|
473
|
+
end
|
474
|
+
end
|
475
|
+
|
476
|
+
def require_rubygems_min_version!(min_version, feature)
|
477
|
+
return if min_version <= Gem::Version.new(Gem::VERSION)
|
478
|
+
|
479
|
+
raise "#{feature} is not supported on your version of RubyGems. " \
|
480
|
+
"You must have RubyGems #{min_version}+ to use this feature."
|
481
|
+
end
|
482
|
+
|
483
|
+
# @version 5.0.0
|
484
|
+
def with_unbundled_env
|
485
|
+
bundler_ver = Gem::Version.new(Bundler::VERSION)
|
486
|
+
if bundler_ver < Gem::Version.new('2.1.0')
|
487
|
+
Bundler.with_clean_env { yield }
|
488
|
+
else
|
489
|
+
Bundler.with_unbundled_env { yield }
|
490
|
+
end
|
432
491
|
end
|
433
492
|
end
|
434
493
|
end
|