tiny-fast-gem 0.0.1
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.
- checksums.yaml +7 -0
- data/puma-8.0.2/History.md +3334 -0
- data/puma-8.0.2/LICENSE +29 -0
- data/puma-8.0.2/README.md +484 -0
- data/puma-8.0.2/bin/puma +10 -0
- data/puma-8.0.2/bin/puma-wild +25 -0
- data/puma-8.0.2/bin/pumactl +12 -0
- data/puma-8.0.2/docs/5.0-Upgrade.md +98 -0
- data/puma-8.0.2/docs/6.0-Upgrade.md +56 -0
- data/puma-8.0.2/docs/7.0-Upgrade.md +52 -0
- data/puma-8.0.2/docs/8.0-Upgrade.md +100 -0
- data/puma-8.0.2/docs/architecture.md +74 -0
- data/puma-8.0.2/docs/compile_options.md +55 -0
- data/puma-8.0.2/docs/deployment.md +137 -0
- data/puma-8.0.2/docs/fork_worker.md +41 -0
- data/puma-8.0.2/docs/grpc.md +62 -0
- data/puma-8.0.2/docs/images/favicon.svg +1 -0
- data/puma-8.0.2/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/puma-8.0.2/docs/images/puma-connection-flow.png +0 -0
- data/puma-8.0.2/docs/images/puma-general-arch.png +0 -0
- data/puma-8.0.2/docs/images/running-puma.svg +1 -0
- data/puma-8.0.2/docs/images/standard-logo.svg +1 -0
- data/puma-8.0.2/docs/java_options.md +54 -0
- data/puma-8.0.2/docs/jungle/README.md +9 -0
- data/puma-8.0.2/docs/jungle/rc.d/README.md +74 -0
- data/puma-8.0.2/docs/jungle/rc.d/puma +61 -0
- data/puma-8.0.2/docs/jungle/rc.d/puma.conf +10 -0
- data/puma-8.0.2/docs/kubernetes.md +73 -0
- data/puma-8.0.2/docs/nginx.md +80 -0
- data/puma-8.0.2/docs/plugins.md +42 -0
- data/puma-8.0.2/docs/rails_dev_mode.md +28 -0
- data/puma-8.0.2/docs/restart.md +65 -0
- data/puma-8.0.2/docs/signals.md +98 -0
- data/puma-8.0.2/docs/stats.md +148 -0
- data/puma-8.0.2/docs/systemd.md +253 -0
- data/puma-8.0.2/docs/testing_benchmarks_local_files.md +150 -0
- data/puma-8.0.2/docs/testing_test_rackup_ci_files.md +36 -0
- data/puma-8.0.2/ext/puma_http11/PumaHttp11Service.java +17 -0
- data/puma-8.0.2/ext/puma_http11/extconf.rb +65 -0
- data/puma-8.0.2/ext/puma_http11/http11_parser.c +1057 -0
- data/puma-8.0.2/ext/puma_http11/http11_parser.h +65 -0
- data/puma-8.0.2/ext/puma_http11/http11_parser.java.rl +131 -0
- data/puma-8.0.2/ext/puma_http11/http11_parser.rl +149 -0
- data/puma-8.0.2/ext/puma_http11/http11_parser_common.rl +54 -0
- data/puma-8.0.2/ext/puma_http11/mini_ssl.c +852 -0
- data/puma-8.0.2/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/puma-8.0.2/ext/puma_http11/org/jruby/puma/EnvKey.java +241 -0
- data/puma-8.0.2/ext/puma_http11/org/jruby/puma/Http11.java +321 -0
- data/puma-8.0.2/ext/puma_http11/org/jruby/puma/Http11Parser.java +441 -0
- data/puma-8.0.2/ext/puma_http11/org/jruby/puma/MiniSSL.java +509 -0
- data/puma-8.0.2/ext/puma_http11/puma_http11.c +499 -0
- data/puma-8.0.2/lib/puma/app/status.rb +104 -0
- data/puma-8.0.2/lib/puma/binder.rb +511 -0
- data/puma-8.0.2/lib/puma/cli.rb +245 -0
- data/puma-8.0.2/lib/puma/client.rb +756 -0
- data/puma-8.0.2/lib/puma/client_env.rb +171 -0
- data/puma-8.0.2/lib/puma/cluster/worker.rb +183 -0
- data/puma-8.0.2/lib/puma/cluster/worker_handle.rb +127 -0
- data/puma-8.0.2/lib/puma/cluster.rb +634 -0
- data/puma-8.0.2/lib/puma/cluster_accept_loop_delay.rb +91 -0
- data/puma-8.0.2/lib/puma/commonlogger.rb +115 -0
- data/puma-8.0.2/lib/puma/configuration.rb +522 -0
- data/puma-8.0.2/lib/puma/const.rb +308 -0
- data/puma-8.0.2/lib/puma/control_cli.rb +320 -0
- data/puma-8.0.2/lib/puma/detect.rb +58 -0
- data/puma-8.0.2/lib/puma/dsl.rb +1562 -0
- data/puma-8.0.2/lib/puma/error_logger.rb +115 -0
- data/puma-8.0.2/lib/puma/events.rb +72 -0
- data/puma-8.0.2/lib/puma/io_buffer.rb +50 -0
- data/puma-8.0.2/lib/puma/jruby_restart.rb +11 -0
- data/puma-8.0.2/lib/puma/json_serialization.rb +96 -0
- data/puma-8.0.2/lib/puma/launcher/bundle_pruner.rb +102 -0
- data/puma-8.0.2/lib/puma/launcher.rb +501 -0
- data/puma-8.0.2/lib/puma/log_writer.rb +153 -0
- data/puma-8.0.2/lib/puma/minissl/context_builder.rb +96 -0
- data/puma-8.0.2/lib/puma/minissl.rb +458 -0
- data/puma-8.0.2/lib/puma/null_io.rb +101 -0
- data/puma-8.0.2/lib/puma/plugin/systemd.rb +90 -0
- data/puma-8.0.2/lib/puma/plugin/tmp_restart.rb +36 -0
- data/puma-8.0.2/lib/puma/plugin.rb +111 -0
- data/puma-8.0.2/lib/puma/rack/builder.rb +297 -0
- data/puma-8.0.2/lib/puma/rack/urlmap.rb +93 -0
- data/puma-8.0.2/lib/puma/rack_default.rb +24 -0
- data/puma-8.0.2/lib/puma/reactor.rb +131 -0
- data/puma-8.0.2/lib/puma/response.rb +532 -0
- data/puma-8.0.2/lib/puma/runner.rb +211 -0
- data/puma-8.0.2/lib/puma/sd_notify.rb +146 -0
- data/puma-8.0.2/lib/puma/server.rb +773 -0
- data/puma-8.0.2/lib/puma/server_plugin_control.rb +32 -0
- data/puma-8.0.2/lib/puma/single.rb +72 -0
- data/puma-8.0.2/lib/puma/state_file.rb +69 -0
- data/puma-8.0.2/lib/puma/thread_pool.rb +517 -0
- data/puma-8.0.2/lib/puma/util.rb +134 -0
- data/puma-8.0.2/lib/puma.rb +88 -0
- data/puma-8.0.2/lib/rack/handler/puma.rb +144 -0
- data/puma-8.0.2/tools/Dockerfile +26 -0
- data/puma-8.0.2/tools/trickletest.rb +44 -0
- data/tiny-fast-gem.gemspec +12 -0
- metadata +138 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Puma
|
|
4
|
+
|
|
5
|
+
#———————————————————————— DO NOT USE — this class is for internal use only ———
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# This module is included in `Client`. It contains code to process the `env`
|
|
9
|
+
# before it is passed to the app.
|
|
10
|
+
#
|
|
11
|
+
module ClientEnv # :nodoc:
|
|
12
|
+
|
|
13
|
+
include Puma::Const
|
|
14
|
+
|
|
15
|
+
# Given a Hash +env+ for the request read from +client+, add
|
|
16
|
+
# and fixup keys to comply with Rack's env guidelines.
|
|
17
|
+
# @param env [Hash] see Puma::Client#env, from request
|
|
18
|
+
# @param client [Puma::Client] only needed for Client#peerip
|
|
19
|
+
#
|
|
20
|
+
def normalize_env
|
|
21
|
+
if host = @env[HTTP_HOST]
|
|
22
|
+
# host can be a hostname, ipv4 or bracketed ipv6. Followed by an optional port.
|
|
23
|
+
if colon = host.rindex("]:") # IPV6 with port
|
|
24
|
+
@env[SERVER_NAME] = host[0, colon+1]
|
|
25
|
+
@env[SERVER_PORT] = host[colon+2, host.bytesize]
|
|
26
|
+
elsif !host.start_with?("[") && colon = host.index(":") # not hostname or IPV4 with port
|
|
27
|
+
@env[SERVER_NAME] = host[0, colon]
|
|
28
|
+
@env[SERVER_PORT] = host[colon+1, host.bytesize]
|
|
29
|
+
else
|
|
30
|
+
@env[SERVER_NAME] = host
|
|
31
|
+
@env[SERVER_PORT] = default_server_port
|
|
32
|
+
end
|
|
33
|
+
else
|
|
34
|
+
@env[SERVER_NAME] = LOCALHOST
|
|
35
|
+
@env[SERVER_PORT] = default_server_port
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
unless @env[REQUEST_PATH]
|
|
39
|
+
# it might be a dumbass full host request header
|
|
40
|
+
uri = begin
|
|
41
|
+
URI.parse(@env[REQUEST_URI])
|
|
42
|
+
rescue URI::InvalidURIError
|
|
43
|
+
raise Puma::HttpParserError
|
|
44
|
+
end
|
|
45
|
+
@env[REQUEST_PATH] = uri.path
|
|
46
|
+
|
|
47
|
+
# A nil env value will cause a LintError (and fatal errors elsewhere),
|
|
48
|
+
# so only set the env value if there actually is a value.
|
|
49
|
+
@env[QUERY_STRING] = uri.query if uri.query
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
@env[PATH_INFO] = @env[REQUEST_PATH].to_s # #to_s in case it's nil
|
|
53
|
+
|
|
54
|
+
# From https://www.ietf.org/rfc/rfc3875 :
|
|
55
|
+
# "Script authors should be aware that the REMOTE_ADDR and
|
|
56
|
+
# REMOTE_HOST meta-variables (see sections 4.1.8 and 4.1.9)
|
|
57
|
+
# may not identify the ultimate source of the request.
|
|
58
|
+
# They identify the client for the immediate request to the
|
|
59
|
+
# server; that client may be a proxy, gateway, or other
|
|
60
|
+
# intermediary acting on behalf of the actual source client."
|
|
61
|
+
#
|
|
62
|
+
|
|
63
|
+
unless @env.key?(REMOTE_ADDR)
|
|
64
|
+
begin
|
|
65
|
+
addr = peerip
|
|
66
|
+
rescue Errno::ENOTCONN
|
|
67
|
+
# Client disconnects can result in an inability to get the
|
|
68
|
+
# peeraddr from the socket; default to unspec.
|
|
69
|
+
if peer_family == Socket::AF_INET6
|
|
70
|
+
addr = UNSPECIFIED_IPV6
|
|
71
|
+
else
|
|
72
|
+
addr = UNSPECIFIED_IPV4
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Set unix socket addrs to localhost
|
|
77
|
+
if addr.empty?
|
|
78
|
+
addr = peer_family == Socket::AF_INET6 ? LOCALHOST_IPV6 : LOCALHOST_IPV4
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
@env[REMOTE_ADDR] = addr
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# The legacy HTTP_VERSION header can be sent as a client header.
|
|
85
|
+
# Rack v4 may remove using HTTP_VERSION. If so, remove this line.
|
|
86
|
+
@env[HTTP_VERSION] = @env[SERVER_PROTOCOL] if @env_set_http_version
|
|
87
|
+
|
|
88
|
+
@env[PUMA_SOCKET] = @io
|
|
89
|
+
|
|
90
|
+
if @env[HTTPS_KEY] && @io.peercert
|
|
91
|
+
@env[PUMA_PEERCERT] = @io.peercert
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
@env[HIJACK_P] = true
|
|
95
|
+
@env[HIJACK] = method(:full_hijack).to_proc
|
|
96
|
+
|
|
97
|
+
@env[RACK_INPUT] = @body || EmptyBody
|
|
98
|
+
@env[RACK_URL_SCHEME] ||= default_server_port == PORT_443 ? HTTPS : HTTP
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Fixup any headers with `,` in the name to have `_` now. We emit
|
|
102
|
+
# headers with `,` in them during the parse phase to avoid ambiguity
|
|
103
|
+
# with the `-` to `_` conversion for critical headers. But here for
|
|
104
|
+
# compatibility, we'll convert them back. This code is written to
|
|
105
|
+
# avoid allocation in the common case (ie there are no headers
|
|
106
|
+
# with `,` in their names), that's why it has the extra conditionals.
|
|
107
|
+
#
|
|
108
|
+
# @note If a normalized version of a `,` header already exists, we ignore
|
|
109
|
+
# the `,` version. This prevents clobbering headers managed by proxies
|
|
110
|
+
# but not by clients (Like X-Forwarded-For).
|
|
111
|
+
#
|
|
112
|
+
# @param env [Hash] see Puma::Client#env, from request, modifies in place
|
|
113
|
+
# @version 5.0.3
|
|
114
|
+
#
|
|
115
|
+
def req_env_post_parse
|
|
116
|
+
to_delete = nil
|
|
117
|
+
to_add = nil
|
|
118
|
+
|
|
119
|
+
@env.each do |k,v|
|
|
120
|
+
if k.start_with?("HTTP_") && k.include?(",") && !UNMASKABLE_HEADERS.key?(k)
|
|
121
|
+
if to_delete
|
|
122
|
+
to_delete << k
|
|
123
|
+
else
|
|
124
|
+
to_delete = [k]
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
new_k = k.tr(",", "_")
|
|
128
|
+
if @env.key?(new_k)
|
|
129
|
+
next
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
unless to_add
|
|
133
|
+
to_add = {}
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
to_add[new_k] = v
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
if to_delete # rubocop:disable Style/SafeNavigation
|
|
141
|
+
to_delete.each { |k| env.delete(k) }
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
if to_add
|
|
145
|
+
@env.merge! to_add
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# A rack extension. If the app writes #call'ables to this
|
|
149
|
+
# array, we will invoke them when the request is done.
|
|
150
|
+
#
|
|
151
|
+
env[RACK_AFTER_REPLY] ||= []
|
|
152
|
+
env[RACK_RESPONSE_FINISHED] ||= []
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
HTTP_ON_VALUES = { "on" => true, HTTPS => true }
|
|
156
|
+
private_constant :HTTP_ON_VALUES
|
|
157
|
+
|
|
158
|
+
# @return [Puma::Const::PORT_443,Puma::Const::PORT_80]
|
|
159
|
+
#
|
|
160
|
+
def default_server_port
|
|
161
|
+
if HTTP_ON_VALUES[@env[HTTPS_KEY]] ||
|
|
162
|
+
@env[HTTP_X_FORWARDED_PROTO]&.start_with?(HTTPS) ||
|
|
163
|
+
@env[HTTP_X_FORWARDED_SCHEME] == HTTPS ||
|
|
164
|
+
@env[HTTP_X_FORWARDED_SSL] == "on"
|
|
165
|
+
PORT_443
|
|
166
|
+
else
|
|
167
|
+
PORT_80
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Puma
|
|
4
|
+
class Cluster < Puma::Runner
|
|
5
|
+
#—————————————————————— DO NOT USE — this class is for internal use only ———
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# This class is instantiated by the `Puma::Cluster` and represents a single
|
|
9
|
+
# worker process.
|
|
10
|
+
#
|
|
11
|
+
# At the core of this class is running an instance of `Puma::Server` which
|
|
12
|
+
# gets created via the `start_server` method from the `Puma::Runner` class
|
|
13
|
+
# that this inherits from.
|
|
14
|
+
class Worker < Puma::Runner # :nodoc:
|
|
15
|
+
attr_reader :index, :master
|
|
16
|
+
|
|
17
|
+
def initialize(index:, master:, launcher:, pipes:, app: nil)
|
|
18
|
+
super(launcher)
|
|
19
|
+
|
|
20
|
+
@index = index
|
|
21
|
+
@master = master
|
|
22
|
+
@check_pipe = pipes[:check_pipe]
|
|
23
|
+
@worker_write = pipes[:worker_write]
|
|
24
|
+
@fork_pipe = pipes[:fork_pipe]
|
|
25
|
+
@wakeup = pipes[:wakeup]
|
|
26
|
+
@app = app
|
|
27
|
+
@server = nil
|
|
28
|
+
@hook_data = {}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def run
|
|
32
|
+
title = "puma: cluster worker #{index}: #{master}"
|
|
33
|
+
title += " [#{@options[:tag]}]" if @options[:tag] && !@options[:tag].empty?
|
|
34
|
+
$0 = title
|
|
35
|
+
|
|
36
|
+
Signal.trap "SIGINT", "IGNORE"
|
|
37
|
+
Signal.trap "SIGCHLD", "DEFAULT"
|
|
38
|
+
|
|
39
|
+
Thread.new do
|
|
40
|
+
Puma.set_thread_name "wrkr check"
|
|
41
|
+
@check_pipe.wait_readable
|
|
42
|
+
log "! Detected parent died, dying"
|
|
43
|
+
exit! 1
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# If we're not running under a Bundler context, then
|
|
47
|
+
# report the info about the context we will be using
|
|
48
|
+
if !ENV['BUNDLE_GEMFILE']
|
|
49
|
+
if File.exist?("Gemfile")
|
|
50
|
+
log "+ Gemfile in context: #{File.expand_path("Gemfile")}"
|
|
51
|
+
elsif File.exist?("gems.rb")
|
|
52
|
+
log "+ Gemfile in context: #{File.expand_path("gems.rb")}"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Invoke any worker boot hooks so they can get
|
|
57
|
+
# things in shape before booting the app.
|
|
58
|
+
@config.run_hooks(:before_worker_boot, index, @log_writer, @hook_data)
|
|
59
|
+
|
|
60
|
+
begin
|
|
61
|
+
@server = start_server
|
|
62
|
+
rescue Exception => e
|
|
63
|
+
log "! Unable to start worker"
|
|
64
|
+
log e
|
|
65
|
+
log e.backtrace.join("\n ")
|
|
66
|
+
exit 1
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
restart_server = Queue.new << true << false
|
|
70
|
+
|
|
71
|
+
fork_worker = @options[:fork_worker] && index == 0
|
|
72
|
+
|
|
73
|
+
if fork_worker
|
|
74
|
+
restart_server.clear
|
|
75
|
+
worker_pids = []
|
|
76
|
+
Signal.trap "SIGCHLD" do
|
|
77
|
+
wakeup! if worker_pids.reject! do |p|
|
|
78
|
+
Process.wait(p, Process::WNOHANG) rescue true
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
Thread.new do
|
|
83
|
+
Puma.set_thread_name "wrkr fork"
|
|
84
|
+
while (idx = @fork_pipe.gets)
|
|
85
|
+
idx = idx.to_i
|
|
86
|
+
if idx == -1 # stop server
|
|
87
|
+
if restart_server.length > 0
|
|
88
|
+
restart_server.clear
|
|
89
|
+
@server.begin_restart(true)
|
|
90
|
+
@config.run_hooks(:before_refork, nil, @log_writer, @hook_data)
|
|
91
|
+
end
|
|
92
|
+
elsif idx == -2 # refork cycle is done
|
|
93
|
+
@config.run_hooks(:after_refork, nil, @log_writer, @hook_data)
|
|
94
|
+
elsif idx == 0 # restart server
|
|
95
|
+
restart_server << true << false
|
|
96
|
+
else # fork worker
|
|
97
|
+
worker_pids << pid = spawn_worker(idx)
|
|
98
|
+
@worker_write << "#{PIPE_FORK}#{pid}:#{idx}\n" rescue nil
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
Signal.trap "SIGTERM" do
|
|
105
|
+
@worker_write << "#{PIPE_EXTERNAL_TERM}#{Process.pid}\n" rescue nil
|
|
106
|
+
restart_server.clear
|
|
107
|
+
@server.stop
|
|
108
|
+
restart_server << false
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
begin
|
|
112
|
+
@worker_write << "#{PIPE_BOOT}#{Process.pid}:#{index}\n"
|
|
113
|
+
rescue SystemCallError, IOError
|
|
114
|
+
STDERR.puts "Master seems to have exited, exiting."
|
|
115
|
+
return
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
while restart_server.pop
|
|
119
|
+
server_thread = @server.run
|
|
120
|
+
|
|
121
|
+
if @log_writer.debug? && index == 0
|
|
122
|
+
debug_loaded_extensions "Loaded Extensions - worker 0:"
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
stat_thread ||= Thread.new(@worker_write) do |io|
|
|
126
|
+
Puma.set_thread_name "stat pld"
|
|
127
|
+
base_payload = "#{PIPE_PING}#{Process.pid}"
|
|
128
|
+
|
|
129
|
+
while true
|
|
130
|
+
begin
|
|
131
|
+
payload = base_payload.dup
|
|
132
|
+
|
|
133
|
+
hsh = @server.stats
|
|
134
|
+
hsh.each do |k, v|
|
|
135
|
+
payload << %Q! "#{k}":#{v || 0},!
|
|
136
|
+
end
|
|
137
|
+
# sub call properly adds 'closing' string
|
|
138
|
+
io << payload.sub(/,\z/, " }\n")
|
|
139
|
+
@server.reset_max
|
|
140
|
+
rescue IOError
|
|
141
|
+
break
|
|
142
|
+
end
|
|
143
|
+
sleep @options[:worker_check_interval]
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
server_thread.join
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Invoke any worker shutdown hooks so they can prevent the worker
|
|
150
|
+
# exiting until any background operations are completed
|
|
151
|
+
@config.run_hooks(:before_worker_shutdown, index, @log_writer, @hook_data)
|
|
152
|
+
ensure
|
|
153
|
+
@worker_write << "#{PIPE_TERM}#{Process.pid}\n" rescue nil
|
|
154
|
+
@worker_write.close
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
private
|
|
158
|
+
|
|
159
|
+
def spawn_worker(idx)
|
|
160
|
+
@config.run_hooks(:before_worker_fork, idx, @log_writer, @hook_data)
|
|
161
|
+
|
|
162
|
+
pid = fork do
|
|
163
|
+
new_worker = Worker.new index: idx,
|
|
164
|
+
master: master,
|
|
165
|
+
launcher: @launcher,
|
|
166
|
+
pipes: { check_pipe: @check_pipe,
|
|
167
|
+
worker_write: @worker_write },
|
|
168
|
+
app: @app
|
|
169
|
+
new_worker.run
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
if !pid
|
|
173
|
+
log "! Complete inability to spawn new workers detected"
|
|
174
|
+
log "! Seppuku is the only choice."
|
|
175
|
+
exit! 1
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
@config.run_hooks(:after_worker_fork, idx, @log_writer, @hook_data)
|
|
179
|
+
pid
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Puma
|
|
4
|
+
class Cluster < Runner
|
|
5
|
+
#—————————————————————— DO NOT USE — this class is for internal use only ———
|
|
6
|
+
|
|
7
|
+
# This class represents a worker process from the perspective of the puma
|
|
8
|
+
# master process. It contains information about the process and its health
|
|
9
|
+
# and it exposes methods to control the process via IPC. It does not
|
|
10
|
+
# include the actual logic executed by the worker process itself. For that,
|
|
11
|
+
# see Puma::Cluster::Worker.
|
|
12
|
+
class WorkerHandle # :nodoc:
|
|
13
|
+
# array of stat 'max' keys
|
|
14
|
+
WORKER_MAX_KEYS = [:backlog_max, :reactor_max]
|
|
15
|
+
|
|
16
|
+
def initialize(idx, pid, phase, options)
|
|
17
|
+
@index = idx
|
|
18
|
+
@pid = pid
|
|
19
|
+
@phase = phase
|
|
20
|
+
@stage = :started
|
|
21
|
+
@signal = "TERM"
|
|
22
|
+
@options = options
|
|
23
|
+
@first_term_sent = nil
|
|
24
|
+
@started_at = Time.now
|
|
25
|
+
@last_checkin = Time.now
|
|
26
|
+
@last_status = {}
|
|
27
|
+
@term = false
|
|
28
|
+
@worker_max = Array.new WORKER_MAX_KEYS.length, 0
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
attr_reader :index, :pid, :phase, :signal, :last_checkin, :last_status, :started_at, :process_status
|
|
32
|
+
|
|
33
|
+
# @version 5.0.0
|
|
34
|
+
attr_writer :pid, :phase, :process_status
|
|
35
|
+
|
|
36
|
+
def booted?
|
|
37
|
+
@stage == :booted
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def uptime
|
|
41
|
+
Time.now - started_at
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def boot!
|
|
45
|
+
@last_checkin = Time.now
|
|
46
|
+
@stage = :booted
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def term!
|
|
50
|
+
@term = true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def term?
|
|
54
|
+
@term
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def ping!(status)
|
|
58
|
+
hsh = {}
|
|
59
|
+
k, v = nil, nil
|
|
60
|
+
status.tr('}{"', '').strip.split(", ") do |kv|
|
|
61
|
+
cntr = 0
|
|
62
|
+
kv.split(':') do |t|
|
|
63
|
+
if cntr == 0
|
|
64
|
+
k = t
|
|
65
|
+
cntr = 1
|
|
66
|
+
else
|
|
67
|
+
v = t
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
hsh[k.to_sym] = v.to_i
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# check stat max values, we can't signal workers to reset the max values,
|
|
74
|
+
# so we do so here
|
|
75
|
+
WORKER_MAX_KEYS.each_with_index do |key, idx|
|
|
76
|
+
next unless hsh[key]
|
|
77
|
+
|
|
78
|
+
if hsh[key] < @worker_max[idx]
|
|
79
|
+
hsh[key] = @worker_max[idx]
|
|
80
|
+
else
|
|
81
|
+
@worker_max[idx] = hsh[key]
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
@last_checkin = Time.now
|
|
85
|
+
@last_status = hsh
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Resets max values to zero. Called whenever `Cluster#stats` is called
|
|
89
|
+
def reset_max
|
|
90
|
+
WORKER_MAX_KEYS.length.times { |idx| @worker_max[idx] = 0 }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# @see Puma::Cluster#check_workers
|
|
94
|
+
# @version 5.0.0
|
|
95
|
+
def ping_timeout
|
|
96
|
+
@last_checkin +
|
|
97
|
+
(booted? ?
|
|
98
|
+
@options[:worker_timeout] :
|
|
99
|
+
@options[:worker_boot_timeout]
|
|
100
|
+
)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def term
|
|
104
|
+
begin
|
|
105
|
+
if @first_term_sent && (Time.now - @first_term_sent) > @options[:worker_shutdown_timeout]
|
|
106
|
+
@signal = "KILL"
|
|
107
|
+
else
|
|
108
|
+
@term ||= true
|
|
109
|
+
@first_term_sent ||= Time.now
|
|
110
|
+
end
|
|
111
|
+
Process.kill @signal, @pid if @pid
|
|
112
|
+
rescue Errno::ESRCH
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def kill
|
|
117
|
+
@signal = 'KILL'
|
|
118
|
+
term
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def hup
|
|
122
|
+
Process.kill "HUP", @pid
|
|
123
|
+
rescue Errno::ESRCH
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|