piesync-puma 3.12.6

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 (82) hide show
  1. checksums.yaml +7 -0
  2. data/History.md +1429 -0
  3. data/LICENSE +26 -0
  4. data/README.md +280 -0
  5. data/bin/puma +10 -0
  6. data/bin/puma-wild +31 -0
  7. data/bin/pumactl +12 -0
  8. data/docs/architecture.md +36 -0
  9. data/docs/deployment.md +91 -0
  10. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  11. data/docs/images/puma-connection-flow.png +0 -0
  12. data/docs/images/puma-general-arch.png +0 -0
  13. data/docs/nginx.md +80 -0
  14. data/docs/plugins.md +28 -0
  15. data/docs/restart.md +39 -0
  16. data/docs/signals.md +96 -0
  17. data/docs/systemd.md +272 -0
  18. data/ext/puma_http11/PumaHttp11Service.java +17 -0
  19. data/ext/puma_http11/ext_help.h +15 -0
  20. data/ext/puma_http11/extconf.rb +15 -0
  21. data/ext/puma_http11/http11_parser.c +1071 -0
  22. data/ext/puma_http11/http11_parser.h +65 -0
  23. data/ext/puma_http11/http11_parser.java.rl +161 -0
  24. data/ext/puma_http11/http11_parser.rl +149 -0
  25. data/ext/puma_http11/http11_parser_common.rl +54 -0
  26. data/ext/puma_http11/io_buffer.c +155 -0
  27. data/ext/puma_http11/mini_ssl.c +494 -0
  28. data/ext/puma_http11/org/jruby/puma/Http11.java +234 -0
  29. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +470 -0
  30. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +352 -0
  31. data/ext/puma_http11/puma_http11.c +500 -0
  32. data/lib/puma.rb +23 -0
  33. data/lib/puma/accept_nonblock.rb +23 -0
  34. data/lib/puma/app/status.rb +74 -0
  35. data/lib/puma/binder.rb +413 -0
  36. data/lib/puma/cli.rb +235 -0
  37. data/lib/puma/client.rb +480 -0
  38. data/lib/puma/cluster.rb +531 -0
  39. data/lib/puma/commonlogger.rb +108 -0
  40. data/lib/puma/compat.rb +14 -0
  41. data/lib/puma/configuration.rb +361 -0
  42. data/lib/puma/const.rb +239 -0
  43. data/lib/puma/control_cli.rb +264 -0
  44. data/lib/puma/convenient.rb +25 -0
  45. data/lib/puma/daemon_ext.rb +33 -0
  46. data/lib/puma/delegation.rb +13 -0
  47. data/lib/puma/detect.rb +15 -0
  48. data/lib/puma/dsl.rb +518 -0
  49. data/lib/puma/events.rb +153 -0
  50. data/lib/puma/io_buffer.rb +9 -0
  51. data/lib/puma/java_io_buffer.rb +47 -0
  52. data/lib/puma/jruby_restart.rb +84 -0
  53. data/lib/puma/launcher.rb +433 -0
  54. data/lib/puma/minissl.rb +285 -0
  55. data/lib/puma/null_io.rb +44 -0
  56. data/lib/puma/plugin.rb +117 -0
  57. data/lib/puma/plugin/tmp_restart.rb +34 -0
  58. data/lib/puma/rack/backports/uri/common_193.rb +33 -0
  59. data/lib/puma/rack/builder.rb +299 -0
  60. data/lib/puma/rack/urlmap.rb +91 -0
  61. data/lib/puma/rack_default.rb +7 -0
  62. data/lib/puma/reactor.rb +347 -0
  63. data/lib/puma/runner.rb +184 -0
  64. data/lib/puma/server.rb +1072 -0
  65. data/lib/puma/single.rb +123 -0
  66. data/lib/puma/state_file.rb +31 -0
  67. data/lib/puma/tcp_logger.rb +41 -0
  68. data/lib/puma/thread_pool.rb +346 -0
  69. data/lib/puma/util.rb +129 -0
  70. data/lib/rack/handler/puma.rb +115 -0
  71. data/tools/jungle/README.md +19 -0
  72. data/tools/jungle/init.d/README.md +61 -0
  73. data/tools/jungle/init.d/puma +421 -0
  74. data/tools/jungle/init.d/run-puma +18 -0
  75. data/tools/jungle/rc.d/README.md +74 -0
  76. data/tools/jungle/rc.d/puma +61 -0
  77. data/tools/jungle/rc.d/puma.conf +10 -0
  78. data/tools/jungle/upstart/README.md +61 -0
  79. data/tools/jungle/upstart/puma-manager.conf +31 -0
  80. data/tools/jungle/upstart/puma.conf +69 -0
  81. data/tools/trickletest.rb +45 -0
  82. metadata +131 -0
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'puma/const'
4
+ require "puma/null_io"
5
+ require 'stringio'
6
+
7
+ module Puma
8
+ # The default implement of an event sink object used by Server
9
+ # for when certain kinds of events occur in the life of the server.
10
+ #
11
+ # The methods available are the events that the Server fires.
12
+ #
13
+ class Events
14
+ class DefaultFormatter
15
+ def call(str)
16
+ str
17
+ end
18
+ end
19
+
20
+ class PidFormatter
21
+ def call(str)
22
+ "[#{$$}] #{str}"
23
+ end
24
+ end
25
+
26
+ include Const
27
+
28
+ # Create an Events object that prints to +stdout+ and +stderr+.
29
+ #
30
+ def initialize(stdout, stderr)
31
+ @formatter = DefaultFormatter.new
32
+ @stdout = stdout
33
+ @stderr = stderr
34
+
35
+ @stdout.sync = true
36
+ @stderr.sync = true
37
+
38
+ @debug = ENV.key? 'PUMA_DEBUG'
39
+
40
+ @hooks = Hash.new { |h,k| h[k] = [] }
41
+ end
42
+
43
+ attr_reader :stdout, :stderr
44
+ attr_accessor :formatter
45
+
46
+ # Fire callbacks for the named hook
47
+ #
48
+ def fire(hook, *args)
49
+ @hooks[hook].each { |t| t.call(*args) }
50
+ end
51
+
52
+ # Register a callback for a given hook
53
+ #
54
+ def register(hook, obj=nil, &blk)
55
+ if obj and blk
56
+ raise "Specify either an object or a block, not both"
57
+ end
58
+
59
+ h = obj || blk
60
+
61
+ @hooks[hook] << h
62
+
63
+ h
64
+ end
65
+
66
+ # Write +str+ to +@stdout+
67
+ #
68
+ def log(str)
69
+ @stdout.puts format(str)
70
+ end
71
+
72
+ def write(str)
73
+ @stdout.write format(str)
74
+ end
75
+
76
+ def debug(str)
77
+ log("% #{str}") if @debug
78
+ end
79
+
80
+ # Write +str+ to +@stderr+
81
+ #
82
+ def error(str)
83
+ @stderr.puts format("ERROR: #{str}")
84
+ exit 1
85
+ end
86
+
87
+ def format(str)
88
+ formatter.call(str)
89
+ end
90
+
91
+ # An HTTP parse error has occurred.
92
+ # +server+ is the Server object, +env+ the request, and +error+ a
93
+ # parsing exception.
94
+ #
95
+ def parse_error(server, env, error)
96
+ @stderr.puts "#{Time.now}: HTTP parse error, malformed request (#{env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR]}): #{error.inspect}\n---\n"
97
+ end
98
+
99
+ # An SSL error has occurred.
100
+ # +server+ is the Server object, +peeraddr+ peer address, +peercert+
101
+ # any peer certificate (if present), and +error+ an exception object.
102
+ #
103
+ def ssl_error(server, peeraddr, peercert, error)
104
+ subject = peercert ? peercert.subject : nil
105
+ @stderr.puts "#{Time.now}: SSL error, peer: #{peeraddr}, peer cert: #{subject}, #{error.inspect}"
106
+ end
107
+
108
+ # An unknown error has occurred.
109
+ # +server+ is the Server object, +error+ an exception object,
110
+ # +kind+ some additional info, and +env+ the request.
111
+ #
112
+ def unknown_error(server, error, kind="Unknown", env=nil)
113
+ if error.respond_to? :render
114
+ error.render "#{Time.now}: #{kind} error", @stderr
115
+ else
116
+ if env
117
+ string_block = [ "#{Time.now}: #{kind} error handling request { #{env['REQUEST_METHOD']} #{env['PATH_INFO']} }" ]
118
+ string_block << error.inspect
119
+ else
120
+ string_block = [ "#{Time.now}: #{kind} error: #{error.inspect}" ]
121
+ end
122
+ string_block << error.backtrace
123
+ @stderr.puts string_block.join("\n")
124
+ end
125
+ end
126
+
127
+ def on_booted(&block)
128
+ register(:on_booted, &block)
129
+ end
130
+
131
+ def fire_on_booted!
132
+ fire(:on_booted)
133
+ end
134
+
135
+ DEFAULT = new(STDOUT, STDERR)
136
+
137
+ # Returns an Events object which writes its status to 2 StringIO
138
+ # objects.
139
+ #
140
+ def self.strings
141
+ Events.new StringIO.new, StringIO.new
142
+ end
143
+
144
+ def self.stdio
145
+ Events.new $stdout, $stderr
146
+ end
147
+
148
+ def self.null
149
+ n = NullIO.new
150
+ Events.new n, n
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'puma/detect'
4
+
5
+ if Puma.jruby?
6
+ require 'puma/java_io_buffer'
7
+ else
8
+ require 'puma/puma_http11'
9
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'java'
4
+
5
+ # Conservative native JRuby/Java implementation of IOBuffer
6
+ # backed by a ByteArrayOutputStream and conversion between
7
+ # Ruby String and Java bytes
8
+ module Puma
9
+ class JavaIOBuffer < java.io.ByteArrayOutputStream
10
+ field_reader :buf
11
+ end
12
+
13
+ class IOBuffer
14
+ BUF_DEFAULT_SIZE = 4096
15
+
16
+ def initialize
17
+ @buf = JavaIOBuffer.new(BUF_DEFAULT_SIZE)
18
+ end
19
+
20
+ def reset
21
+ @buf.reset
22
+ end
23
+
24
+ def <<(str)
25
+ bytes = str.to_java_bytes
26
+ @buf.write(bytes, 0, bytes.length)
27
+ end
28
+
29
+ def append(*strs)
30
+ strs.each { |s| self << s; }
31
+ end
32
+
33
+ def to_s
34
+ String.from_java_bytes @buf.to_byte_array
35
+ end
36
+
37
+ alias_method :to_str, :to_s
38
+
39
+ def used
40
+ @buf.size
41
+ end
42
+
43
+ def capacity
44
+ @buf.buf.length
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+
5
+ module Puma
6
+ module JRubyRestart
7
+ extend FFI::Library
8
+ ffi_lib 'c'
9
+
10
+ attach_function :execlp, [:string, :varargs], :int
11
+ attach_function :chdir, [:string], :int
12
+ attach_function :fork, [], :int
13
+ attach_function :exit, [:int], :void
14
+ attach_function :setsid, [], :int
15
+
16
+ def self.chdir_exec(dir, argv)
17
+ chdir(dir)
18
+ cmd = argv.first
19
+ argv = ([:string] * argv.size).zip(argv).flatten
20
+ argv << :string
21
+ argv << nil
22
+ execlp(cmd, *argv)
23
+ raise SystemCallError.new(FFI.errno)
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
+ end
84
+ end
@@ -0,0 +1,433 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'puma/events'
4
+ require 'puma/detect'
5
+
6
+ require 'puma/cluster'
7
+ require 'puma/single'
8
+
9
+ require 'puma/const'
10
+
11
+ require 'puma/binder'
12
+
13
+ module Puma
14
+ # Puma::Launcher is the single entry point for starting a Puma server based on user
15
+ # configuration. It is responsible for taking user supplied arguments and resolving them
16
+ # with configuration in `config/puma.rb` or `config/puma/<env>.rb`.
17
+ #
18
+ # It is responsible for either launching a cluster of Puma workers or a single
19
+ # puma server.
20
+ class Launcher
21
+ KEYS_NOT_TO_PERSIST_IN_STATE = [
22
+ :logger, :lowlevel_error_handler,
23
+ :before_worker_shutdown, :before_worker_boot, :before_worker_fork,
24
+ :after_worker_boot, :before_fork, :on_restart
25
+ ]
26
+ # Returns an instance of Launcher
27
+ #
28
+ # +conf+ A Puma::Configuration object indicating how to run the server.
29
+ #
30
+ # +launcher_args+ A Hash that currently has one required key `:events`,
31
+ # this is expected to hold an object similar to an `Puma::Events.stdio`,
32
+ # this object will be responsible for broadcasting Puma's internal state
33
+ # to a logging destination. An optional key `:argv` can be supplied,
34
+ # this should be an array of strings, these arguments are re-used when
35
+ # restarting the puma server.
36
+ #
37
+ # Examples:
38
+ #
39
+ # conf = Puma::Configuration.new do |user_config|
40
+ # user_config.threads 1, 10
41
+ # user_config.app do |env|
42
+ # [200, {}, ["hello world"]]
43
+ # end
44
+ # end
45
+ # Puma::Launcher.new(conf, events: Puma::Events.stdio).run
46
+ def initialize(conf, launcher_args={})
47
+ @runner = nil
48
+ @events = launcher_args[:events] || Events::DEFAULT
49
+ @argv = launcher_args[:argv] || []
50
+ @original_argv = @argv.dup
51
+ @config = conf
52
+
53
+ @binder = Binder.new(@events)
54
+ @binder.import_from_env
55
+
56
+ @environment = conf.environment
57
+
58
+ # Advertise the Configuration
59
+ Puma.cli_config = @config if defined?(Puma.cli_config)
60
+
61
+ @config.load
62
+
63
+ @options = @config.options
64
+ @config.clamp
65
+
66
+ generate_restart_data
67
+
68
+ if clustered? && !Process.respond_to?(:fork)
69
+ unsupported "worker mode not supported on #{RUBY_ENGINE} on this platform"
70
+ end
71
+
72
+ if @options[:daemon] && Puma.windows?
73
+ unsupported 'daemon mode not supported on Windows'
74
+ end
75
+
76
+ Dir.chdir(@restart_dir)
77
+
78
+ prune_bundler if prune_bundler?
79
+
80
+ @environment = @options[:environment] if @options[:environment]
81
+ set_rack_environment
82
+
83
+ if clustered?
84
+ @events.formatter = Events::PidFormatter.new
85
+ @options[:logger] = @events
86
+
87
+ @runner = Cluster.new(self, @events)
88
+ else
89
+ @runner = Single.new(self, @events)
90
+ end
91
+ Puma.stats_object = @runner
92
+
93
+ @status = :run
94
+ end
95
+
96
+ attr_reader :binder, :events, :config, :options, :restart_dir
97
+
98
+ # Return stats about the server
99
+ def stats
100
+ @runner.stats
101
+ end
102
+
103
+ # Write a state file that can be used by pumactl to control
104
+ # the server
105
+ def write_state
106
+ write_pid
107
+
108
+ path = @options[:state]
109
+ return unless path
110
+
111
+ require 'puma/state_file'
112
+
113
+ sf = StateFile.new
114
+ sf.pid = Process.pid
115
+ sf.control_url = @options[:control_url]
116
+ sf.control_auth_token = @options[:control_auth_token]
117
+
118
+ sf.save path
119
+ end
120
+
121
+ # Delete the configured pidfile
122
+ def delete_pidfile
123
+ path = @options[:pidfile]
124
+ File.unlink(path) if path && File.exist?(path)
125
+ end
126
+
127
+ # If configured, write the pid of the current process out
128
+ # to a file.
129
+ def write_pid
130
+ path = @options[:pidfile]
131
+ return unless path
132
+
133
+ File.open(path, 'w') { |f| f.puts Process.pid }
134
+ cur = Process.pid
135
+ at_exit do
136
+ delete_pidfile if cur == Process.pid
137
+ end
138
+ end
139
+
140
+ # Begin async shutdown of the server
141
+ def halt
142
+ @status = :halt
143
+ @runner.halt
144
+ end
145
+
146
+ # Begin async shutdown of the server gracefully
147
+ def stop
148
+ @status = :stop
149
+ @runner.stop
150
+ end
151
+
152
+ # Begin async restart of the server
153
+ def restart
154
+ @status = :restart
155
+ @runner.restart
156
+ end
157
+
158
+ # Begin a phased restart if supported
159
+ def phased_restart
160
+ unless @runner.respond_to?(:phased_restart) and @runner.phased_restart
161
+ log "* phased-restart called but not available, restarting normally."
162
+ return restart
163
+ end
164
+ true
165
+ end
166
+
167
+ # Run the server. This blocks until the server is stopped
168
+ def run
169
+ previous_env =
170
+ if defined?(Bundler)
171
+ env = Bundler::ORIGINAL_ENV.dup
172
+ # add -rbundler/setup so we load from Gemfile when restarting
173
+ bundle = "-rbundler/setup"
174
+ env["RUBYOPT"] = [env["RUBYOPT"], bundle].join(" ").lstrip unless env["RUBYOPT"].to_s.include?(bundle)
175
+ env
176
+ else
177
+ ENV.to_h
178
+ end
179
+
180
+ @config.clamp
181
+
182
+ @config.plugins.fire_starts self
183
+
184
+ setup_signals
185
+ set_process_title
186
+ @runner.run
187
+
188
+ case @status
189
+ when :halt
190
+ log "* Stopping immediately!"
191
+ when :run, :stop
192
+ graceful_stop
193
+ when :restart
194
+ log "* Restarting..."
195
+ ENV.replace(previous_env)
196
+ @runner.before_restart
197
+ restart!
198
+ when :exit
199
+ # nothing
200
+ end
201
+ end
202
+
203
+ # Return which tcp port the launcher is using, if it's using TCP
204
+ def connected_port
205
+ @binder.connected_port
206
+ end
207
+
208
+ def restart_args
209
+ cmd = @options[:restart_cmd]
210
+ if cmd
211
+ cmd.split(' ') + @original_argv
212
+ else
213
+ @restart_argv
214
+ end
215
+ end
216
+
217
+ private
218
+
219
+ def reload_worker_directory
220
+ @runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
221
+ end
222
+
223
+ def restart!
224
+ @config.run_hooks :on_restart, self
225
+
226
+ if Puma.jruby?
227
+ close_binder_listeners
228
+
229
+ require 'puma/jruby_restart'
230
+ JRubyRestart.chdir_exec(@restart_dir, restart_args)
231
+ elsif Puma.windows?
232
+ close_binder_listeners
233
+
234
+ argv = restart_args
235
+ Dir.chdir(@restart_dir)
236
+ Kernel.exec(*argv)
237
+ else
238
+ redirects = {:close_others => true}
239
+ @binder.listeners.each_with_index do |(l, io), i|
240
+ ENV["PUMA_INHERIT_#{i}"] = "#{io.to_i}:#{l}"
241
+ redirects[io.to_i] = io.to_i
242
+ end
243
+
244
+ argv = restart_args
245
+ Dir.chdir(@restart_dir)
246
+ argv += [redirects] if RUBY_VERSION >= '1.9'
247
+ Kernel.exec(*argv)
248
+ end
249
+ end
250
+
251
+ def prune_bundler
252
+ return unless defined?(Bundler)
253
+ puma = Bundler.rubygems.loaded_specs("puma")
254
+ dirs = puma.require_paths.map { |x| File.join(puma.full_gem_path, x) }
255
+ puma_lib_dir = dirs.detect { |x| File.exist? File.join(x, '../bin/puma-wild') }
256
+
257
+ unless puma_lib_dir
258
+ log "! Unable to prune Bundler environment, continuing"
259
+ return
260
+ end
261
+
262
+ deps = puma.runtime_dependencies.map do |d|
263
+ spec = Bundler.rubygems.loaded_specs(d.name)
264
+ "#{d.name}:#{spec.version.to_s}"
265
+ end
266
+
267
+ log '* Pruning Bundler environment'
268
+ home = ENV['GEM_HOME']
269
+ Bundler.with_clean_env do
270
+ ENV['GEM_HOME'] = home
271
+ ENV['PUMA_BUNDLER_PRUNED'] = '1'
272
+ wild = File.expand_path(File.join(puma_lib_dir, "../bin/puma-wild"))
273
+ args = [Gem.ruby, wild, '-I', dirs.join(':'), deps.join(',')] + @original_argv
274
+ # Ruby 2.0+ defaults to true which breaks socket activation
275
+ args += [{:close_others => false}] if RUBY_VERSION >= '2.0'
276
+ Kernel.exec(*args)
277
+ end
278
+ end
279
+
280
+ def log(str)
281
+ @events.log str
282
+ end
283
+
284
+ def clustered?
285
+ (@options[:workers] || 0) > 0
286
+ end
287
+
288
+ def unsupported(str)
289
+ @events.error(str)
290
+ raise UnsupportedOption
291
+ end
292
+
293
+ def graceful_stop
294
+ @runner.stop_blocked
295
+ log "=== puma shutdown: #{Time.now} ==="
296
+ log "- Goodbye!"
297
+ end
298
+
299
+ def set_process_title
300
+ Process.respond_to?(:setproctitle) ? Process.setproctitle(title) : $0 = title
301
+ end
302
+
303
+ def title
304
+ buffer = "puma #{Puma::Const::VERSION} (#{@options[:binds].join(',')})"
305
+ buffer += " [#{@options[:tag]}]" if @options[:tag] && !@options[:tag].empty?
306
+ buffer
307
+ end
308
+
309
+ def set_rack_environment
310
+ @options[:environment] = environment
311
+ ENV['RACK_ENV'] = environment
312
+ end
313
+
314
+ def environment
315
+ @environment
316
+ end
317
+
318
+ def prune_bundler?
319
+ @options[:prune_bundler] && clustered? && !@options[:preload_app]
320
+ end
321
+
322
+ def close_binder_listeners
323
+ @binder.listeners.each do |l, io|
324
+ io.close
325
+ uri = URI.parse(l)
326
+ next unless uri.scheme == 'unix'
327
+ File.unlink("#{uri.host}#{uri.path}")
328
+ end
329
+ end
330
+
331
+
332
+ def generate_restart_data
333
+ if dir = @options[:directory]
334
+ @restart_dir = dir
335
+
336
+ elsif Puma.windows?
337
+ # I guess the value of PWD is garbage on windows so don't bother
338
+ # using it.
339
+ @restart_dir = Dir.pwd
340
+
341
+ # Use the same trick as unicorn, namely favor PWD because
342
+ # it will contain an unresolved symlink, useful for when
343
+ # the pwd is /data/releases/current.
344
+ elsif dir = ENV['PWD']
345
+ s_env = File.stat(dir)
346
+ s_pwd = File.stat(Dir.pwd)
347
+
348
+ if s_env.ino == s_pwd.ino and (Puma.jruby? or s_env.dev == s_pwd.dev)
349
+ @restart_dir = dir
350
+ end
351
+ end
352
+
353
+ @restart_dir ||= Dir.pwd
354
+
355
+ # if $0 is a file in the current directory, then restart
356
+ # it the same, otherwise add -S on there because it was
357
+ # picked up in PATH.
358
+ #
359
+ if File.exist?($0)
360
+ arg0 = [Gem.ruby, $0]
361
+ else
362
+ arg0 = [Gem.ruby, "-S", $0]
363
+ end
364
+
365
+ # Detect and reinject -Ilib from the command line, used for testing without bundler
366
+ # cruby has an expanded path, jruby has just "lib"
367
+ lib = File.expand_path "lib"
368
+ arg0[1,0] = ["-I", lib] if [lib, "lib"].include?($LOAD_PATH[0])
369
+
370
+ if defined? Puma::WILD_ARGS
371
+ @restart_argv = arg0 + Puma::WILD_ARGS + @original_argv
372
+ else
373
+ @restart_argv = arg0 + @original_argv
374
+ end
375
+ end
376
+
377
+ def setup_signals
378
+ begin
379
+ Signal.trap "SIGUSR2" do
380
+ restart
381
+ end
382
+ rescue Exception
383
+ log "*** SIGUSR2 not implemented, signal based restart unavailable!"
384
+ end
385
+
386
+ unless Puma.jruby?
387
+ begin
388
+ Signal.trap "SIGUSR1" do
389
+ phased_restart
390
+ end
391
+ rescue Exception
392
+ log "*** SIGUSR1 not implemented, signal based restart unavailable!"
393
+ end
394
+ end
395
+
396
+ begin
397
+ Signal.trap "SIGTERM" do
398
+ graceful_stop
399
+
400
+ raise SignalException, "SIGTERM"
401
+ end
402
+ rescue Exception
403
+ log "*** SIGTERM not implemented, signal based gracefully stopping unavailable!"
404
+ end
405
+
406
+ begin
407
+ Signal.trap "SIGINT" do
408
+ if Puma.jruby?
409
+ @status = :exit
410
+ graceful_stop
411
+ exit
412
+ end
413
+
414
+ stop
415
+ end
416
+ rescue Exception
417
+ log "*** SIGINT not implemented, signal based gracefully stopping unavailable!"
418
+ end
419
+
420
+ begin
421
+ Signal.trap "SIGHUP" do
422
+ if @runner.redirected_io?
423
+ @runner.redirect_io
424
+ else
425
+ stop
426
+ end
427
+ end
428
+ rescue Exception
429
+ log "*** SIGHUP not implemented, signal based logs reopening unavailable!"
430
+ end
431
+ end
432
+ end
433
+ end