1
0
Fork 0
mirror of https://github.com/puma/puma.git synced 2022-11-09 13:48:40 -05:00

Documentation - add version info, misc fixes [ci skip] (#2368)

This commit is contained in:
MSP-Greg 2020-09-17 10:15:19 -05:00 committed by GitHub
parent 18f1810c9c
commit 038a0d9da9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 148 additions and 56 deletions

View file

@ -38,10 +38,10 @@ Puma cluster responds to these signals:
- `TERM` send `TERM` to worker. Worker will attempt to finish then exit.
- `USR2` restart workers. This also reloads puma configuration file, if there is one.
- `USR1` restart workers in phases, a rolling restart. This will not reload configuration file.
- `HUP` reopen log files defined in stdout_redirect configuration parameter. If there is no stdout_redirect option provided it will behave like `INT`
- `INT` equivalent of sending Ctrl-C to cluster. Will attempt to finish then exit.
- `HUP ` reopen log files defined in stdout_redirect configuration parameter. If there is no stdout_redirect option provided it will behave like `INT`
- `INT ` equivalent of sending Ctrl-C to cluster. Will attempt to finish then exit.
- `CHLD`
- `URG` refork workers in phases from worker 0, if `fork_workers` option is enabled.
- `URG ` refork workers in phases from worker 0, if `fork_workers` option is enabled.
## Callbacks order in case of different signals

View file

@ -463,6 +463,9 @@ VALUE engine_peercert(VALUE self) {
return rb_cert_buf;
}
/* @see Puma::MiniSSL::Socket#ssl_version_state
* @version 5.0.0
*/
static VALUE
engine_ssl_vers_st(VALUE self) {
ms_conn* conn;

View file

@ -27,6 +27,7 @@ module Puma
@get_stats.stats.to_json
end
# @version 5.0.0
def self.stats_hash
@get_stats.stats
end

View file

@ -50,7 +50,12 @@ module Puma
@ios = []
end
attr_reader :ios, :listeners, :unix_paths, :proto_env, :envs, :activated_sockets, :inherited_fds
attr_reader :ios
# @version 5.0.0
attr_reader :activated_sockets, :envs, :inherited_fds, :listeners, :proto_env, , :unix_paths
# @version 5.0.0
attr_writer :ios, :listeners
def env(sock)
@ -61,10 +66,12 @@ module Puma
@ios.each { |i| i.close }
end
# @version 5.0.0
def connected_ports
ios.map { |io| io.addr[1] }.uniq
end
# @version 5.0.0
def create_inherited_fds(env_hash)
env_hash.select {|k,v| k =~ /PUMA_INHERIT_\d+/}.each do |_k, v|
fd, url = v.split(":", 2)
@ -75,7 +82,9 @@ module Puma
# systemd socket activation.
# LISTEN_FDS = number of listening sockets. e.g. 2 means accept on 2 sockets w/descriptors 3 and 4.
# LISTEN_PID = PID of the service process, aka us
# see https://www.freedesktop.org/software/systemd/man/systemd-socket-activate.html
# @see https://www.freedesktop.org/software/systemd/man/systemd-socket-activate.html
# @version 5.0.0
#
def create_activated_fds(env_hash)
return [] unless env_hash['LISTEN_FDS'] && env_hash['LISTEN_PID'].to_i == $$
env_hash['LISTEN_FDS'].to_i.times do |index|
@ -373,6 +382,7 @@ module Puma
redirects
end
# @version 5.0.0
def redirects_for_restart_env
listeners.each_with_object({}).with_index do |(listen, memo), i|
memo["PUMA_INHERIT_#{i}"] = "#{listen[1].to_i}:#{listen[0]}"
@ -387,6 +397,7 @@ module Puma
end.map { |addrinfo| addrinfo.ip_address }.uniq
end
# @version 5.0.0
def socket_activation_fd(int)
int + 3 # 3 is the magic number you add to follow the SA protocol
end

View file

@ -280,6 +280,8 @@ module Puma
# Returns true if the persistent connection can be closed immediately
# without waiting for the configured idle/shutdown timeout.
# @version 5.0.0
#
def can_close?
# Allow connection to close if it's received at least one full request
# and hasn't received any data for a future request.
@ -443,6 +445,7 @@ module Puma
end
end
# @version 5.0.0
def write_chunk(str)
@chunked_content_length += @body.write(str)
end

View file

@ -77,6 +77,8 @@ module Puma
end
attr_reader :index, :pid, :phase, :signal, :last_checkin, :last_status, :started_at
# @version 5.0.0
attr_writer :pid, :phase
def booted?
@ -98,6 +100,8 @@ module Puma
@last_status = JSON.parse(status, symbolize_names: true)
end
# @see Puma::Cluster#check_workers
# @version 5.0.0
def ping_timeout
@last_checkin +
(booted? ?
@ -160,6 +164,7 @@ module Puma
end
end
# @version 5.0.0
def spawn_worker(idx, master)
@launcher.config.run_hooks :before_worker_fork, idx, @launcher.events
@ -419,6 +424,7 @@ module Puma
@options[:preload_app]
end
# @version 5.0.0
def fork_worker!
if (worker = @workers.find { |w| w.index == 0 })
worker.phase += 1
@ -640,6 +646,7 @@ module Puma
end
end
# @version 5.0.0
def timeout_workers
@workers.each do |w|
if !w.term? && w.ping_timeout <= Time.now
@ -649,6 +656,7 @@ module Puma
end
end
# @version 5.0.0
def nakayoshi_gc
return unless @options[:nakayoshi_fork]
log "! Promoting existing objects to old generation..."

View file

@ -173,6 +173,7 @@ module Puma
self
end
# @version 5.0.0
def default_max_threads
Puma.mri? ? 5 : 16
end

View file

@ -12,6 +12,8 @@ module Puma
class ControlCLI
COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory gc gc-stats thread-backtraces refork}
# @version 5.0.0
PRINTABLE_COMMANDS = %w{gc-stats stats thread-backtraces}
def initialize(argv, stdout=STDOUT, stderr=STDERR)

View file

@ -20,10 +20,12 @@ module Puma
IS_WINDOWS
end
# @version 5.0.0
def self.mri?
RUBY_ENGINE == 'ruby' || RUBY_ENGINE.nil?
end
# @version 5.0.0
def self.forkable?
::Process.respond_to?(:fork)
end

View file

@ -14,22 +14,23 @@ module Puma
# end
# config.load
#
# puts config.options[:binds]
# "tcp://127.0.0.1:3001"
# puts config.options[:binds] # => "tcp://127.0.0.1:3001"
#
# Used to load file:
#
#
# $ cat puma_config.rb
# port 3002
# port 3002
#
# Resulting configuration:
#
# config = Configuration.new(config_file: "puma_config.rb")
# config.load
#
# puts config.options[:binds]
# # => "tcp://127.0.0.1:3002"
# puts config.options[:binds] # => "tcp://127.0.0.1:3002"
#
# You can also find many examples being used by the test suite in
# +test/config+.
#
class DSL
include ConfigDefault
@ -98,6 +99,9 @@ module Puma
# [body]
# ]
# end
#
# @see Puma::Configuration#app
#
def app(obj=nil, &block)
obj ||= block
@ -160,12 +164,12 @@ module Puma
#
# You can use query parameters within the url to specify options:
#
# - Set the socket backlog depth with +backlog+, default is 1024.
# - Set up an SSL certificate with +key+ & +cert+.
# - Set whether to optimize for low latency instead of throughput with
# +low_latency+, default is to optimize for low latency. This is done
# via +Socket::TCP_NODELAY+.
# - Set socket permissions with +umask+.
# * Set the socket backlog depth with +backlog+, default is 1024.
# * Set up an SSL certificate with +key+ & +cert+.
# * Set whether to optimize for low latency instead of throughput with
# +low_latency+, default is to optimize for low latency. This is done
# via +Socket::TCP_NODELAY+.
# * Set socket permissions with +umask+.
#
# @example Backlog depth
# bind 'unix:///var/run/puma.sock?backlog=512'
@ -175,6 +179,9 @@ module Puma
# bind 'tcp://0.0.0.0:9292?low_latency=false'
# @example Socket permissions
# bind 'unix:///var/run/puma.sock?umask=0111'
# @see Puma::Runner#load_and_bind
# @see Puma::Cluster#run
#
def bind(url)
@options[:binds] ||= []
@options[:binds] << url
@ -193,13 +200,14 @@ module Puma
bind "tcp://#{host}:#{port}"
end
# Define how long persistent connections can be idle before Puma closes
# them.
# Define how long persistent connections can be idle before Puma closes them.
# @see Puma::Server.new
def persistent_timeout(seconds)
@options[:persistent_timeout] = Integer(seconds)
end
# Define how long the tcp socket stays open, if no data has been received.
# @see Puma::Server.new
def first_data_timeout(seconds)
@options[:first_data_timeout] = Integer(seconds)
end
@ -210,10 +218,11 @@ module Puma
@options[:clean_thread_locals] = which
end
# When shutting down, drain the accept socket of pending
# connections and process them. This loops over the accept
# socket until there are no more read events and then stops
# looking and waits for the requests to finish.
# When shutting down, drain the accept socket of pending connections and
# process them. This loops over the accept socket until there are no more
# read events and then stops looking and waits for the requests to finish.
# @see Puma::Server#graceful_shutdown
#
def drain_on_shutdown(which=true)
@options[:drain_on_shutdown] = which
end
@ -236,6 +245,7 @@ module Puma
#
# Puma always waits a few seconds after killing a thread for it to try
# to finish up it's work, even in :immediately mode.
# @see Puma::Server#graceful_shutdown
def force_shutdown_after(val=:forever)
i = case val
when :forever
@ -315,7 +325,7 @@ module Puma
@options[:early_hints] = answer
end
# Redirect STDOUT and STDERR to files specified. The +append+ parameter
# Redirect +STDOUT+ and +STDERR+ to files specified. The +append+ parameter
# specifies whether the output is appended, the default is +false+.
#
# @example
@ -356,8 +366,8 @@ module Puma
@options[:max_threads] = max
end
# Instead of "bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'" you
# can also use the "ssl_bind" option.
# Instead of `bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'` you
# can also use the this method.
#
# @example
# ssl_bind '127.0.0.1', '9292', {
@ -403,6 +413,8 @@ module Puma
#
# @example
# state_permission 0600
# @version 5.0.0
#
def state_permission(permission)
@options[:state_permission] = permission
end
@ -413,6 +425,7 @@ module Puma
# The default is 0.
#
# @note Cluster mode only.
# @see Puma::Cluster
def workers(count)
@options[:workers] = count.to_i
end
@ -516,7 +529,8 @@ module Puma
# on_refork do
# 3.times {GC.start}
# end
# @version 5.0.0
#
def on_refork(&block)
@options[:before_refork] ||= []
@options[:before_refork] << block
@ -582,7 +596,7 @@ module Puma
# new Bundler context and thus can float around as the release
# dictates.
#
# See also: extra_runtime_dependencies
# @see extra_runtime_dependencies
#
# @note This is incompatible with +preload_app!+.
# @note This is only supported for RubyGems 2.2+
@ -599,6 +613,9 @@ module Puma
#
# @example
# raise_exception_on_sigterm false
# @see Puma::Launcher#setup_signals
# @see Puma::Cluster#setup_signals
#
def raise_exception_on_sigterm(answer=true)
@options[:raise_exception_on_sigterm] = answer
end
@ -614,6 +631,8 @@ module Puma
# extra_runtime_dependencies ['gem_name_1', 'gem_name_2']
# @example
# extra_runtime_dependencies ['puma_worker_killer', 'puma-heroku']
# @see Puma::Launcher#extra_runtime_deps_directories
#
def extra_runtime_dependencies(answer = [])
@options[:extra_runtime_dependencies] = Array(answer)
end
@ -641,6 +660,8 @@ module Puma
# @note Cluster mode only.
# @example
# worker_timeout 60
# @see Puma::Cluster::Worker#ping_timeout
#
def worker_timeout(timeout)
timeout = Integer(timeout)
min = Const::WORKER_CHECK_INTERVAL
@ -657,15 +678,20 @@ module Puma
# If unspecified, this defaults to the value of worker_timeout.
#
# @note Cluster mode only.
# @example:
#
# @example
# worker_boot_timeout 60
# @see Puma::Cluster::Worker#ping_timeout
#
def worker_boot_timeout(timeout)
@options[:worker_boot_timeout] = Integer(timeout)
end
# Set the timeout for worker shutdown
# Set the timeout for worker shutdown.
#
# @note Cluster mode only.
# @see Puma::Cluster::Worker#term
#
def worker_shutdown_timeout(timeout)
@options[:worker_shutdown_timeout] = Integer(timeout)
end
@ -683,6 +709,7 @@ module Puma
# slow clients will occupy a handler thread while the request
# is being sent. A reverse proxy, such as nginx, can handle
# slow clients and queue requests before they reach Puma.
# @see Puma::Server
def queue_requests(answer=true)
@options[:queue_requests] = answer
end
@ -690,6 +717,7 @@ module Puma
# When a shutdown is requested, the backtraces of all the
# threads will be written to $stdout. This can help figure
# out why shutdown is hanging.
#
def shutdown_debug(val=true)
@options[:shutdown_debug] = val
end
@ -700,6 +728,10 @@ module Puma
# requests to pick up new requests first.
#
# Only works on MRI. For all other interpreters, this setting does nothing.
# @see Puma::Server#handle_servers
# @see Puma::ThreadPool#wait_for_less_busy_worker
# @version 5.0.0
#
def wait_for_less_busy_worker(val=0.005)
@options[:wait_for_less_busy_worker] = val.to_f
end
@ -711,18 +743,18 @@ module Puma
#
# There are 4 possible values:
#
# * :socket (the default) - read the peername from the socket using the
# syscall. This is the normal behavior.
# * :localhost - set the remote address to "127.0.0.1"
# * header: http_header - set the remote address to the value of the
# provided http header. For instance:
# `set_remote_address header: "X-Real-IP"`.
# Only the first word (as separated by spaces or comma)
# is used, allowing headers such as X-Forwarded-For
# to be used as well.
# * Any string - this allows you to hardcode remote address to any value
# you wish. Because Puma never uses this field anyway, it's
# format is entirely in your hands.
# 1. **:socket** (the default) - read the peername from the socket using the
# syscall. This is the normal behavior.
# 2. **:localhost** - set the remote address to "127.0.0.1"
# 3. **header: <http_header>**- set the remote address to the value of the
# provided http header. For instance:
# `set_remote_address header: "X-Real-IP"`.
# Only the first word (as separated by spaces or comma) is used, allowing
# headers such as X-Forwarded-For to be used as well.
# 4. **\<Any string\>** - this allows you to hardcode remote address to any value
# you wish. Because Puma never uses this field anyway, it's format is
# entirely in your hands.
#
def set_remote_address(val=:socket)
case val
when :socket
@ -756,6 +788,8 @@ module Puma
# (default 1000), or pass 0 to disable auto refork.
#
# @note Cluster mode only.
# @version 5.0.0
#
def fork_worker(after_requests=1000)
@options[:fork_worker] = Integer(after_requests)
end
@ -769,6 +803,10 @@ module Puma
# also increase time to boot and fork. See your logs for details on how much
# time this adds to your boot process. For most apps, it will be less than one
# second.
#
# @see Puma::Cluster#nakayoshi_gc
# @version 5.0.0
#
def nakayoshi_fork(enabled=true)
@options[:nakayoshi_fork] = enabled
end

View file

@ -4,6 +4,7 @@ require 'puma/const'
module Puma
# The implementation of a detailed error logging.
# @version 5.0.0
#
class ErrorLogger
include Const

View file

@ -91,6 +91,7 @@ module Puma
# An HTTP connection error has occurred.
# +error+ a connection exception, +req+ the request,
# and +text+ additional info
# @version 5.0.0
#
def connection_error(error, req, text="HTTP connection error")
@error_logger.info(error: error, req: req, text: text)
@ -124,6 +125,7 @@ module Puma
# Log occurred error debug dump.
# +error+ an exception object, +req+ the request,
# and +text+ additional info
# @version 5.0.0
#
def debug_error(error, req=nil, text="")
@error_logger.debug(error: error, req: req, text: text)

View file

@ -188,6 +188,7 @@ module Puma
end
# Return all tcp ports the launcher may be using, TCP or SSL
# @version 5.0.0
def connected_ports
@binder.connected_ports
end
@ -206,6 +207,7 @@ module Puma
@binder.close_listeners
end
# @version 5.0.0
def thread_status
Thread.list.each do |thread|
name = "Thread: TID-#{thread.object_id.to_s(36)}"
@ -478,6 +480,7 @@ module Puma
"You must have RubyGems #{min_version}+ to use this feature."
end
# @version 5.0.0
def with_unbundled_env
bundler_ver = Gem::Version.new(Bundler::VERSION)
if bundler_ver < Gem::Version.new('2.1.0')

View file

@ -10,8 +10,9 @@ require 'puma/puma_http11'
module Puma
module MiniSSL
# define constant at runtime, as it's easy to determine at built time,
# Define constant at runtime, as it's easy to determine at built time,
# but Puma could (it shouldn't) be loaded with an older OpenSSL version
# @version 5.0.0
HAS_TLS1_3 = !IS_JRUBY &&
(OPENSSL_VERSION[/ \d+\.\d+\.\d+/].split('.').map(&:to_i) <=> [1,1,1]) != -1 &&
(OPENSSL_LIBRARY_VERSION[/ \d+\.\d+\.\d+/].split('.').map(&:to_i) <=> [1,1,1]) !=-1
@ -31,19 +32,21 @@ module Puma
@socket.closed?
end
# returns a two element array
# first is protocol version (SSL_get_version)
# Returns a two element array,
# first is protocol version (SSL_get_version),
# second is 'handshake' state (SSL_state_string)
#
# used for dropping tcp connections to ssl
# see OpenSSL ssl/ssl_stat.c SSL_state_string for info
# Used for dropping tcp connections to ssl.
# See OpenSSL ssl/ssl_stat.c SSL_state_string for info
# @version 5.0.0
#
def ssl_version_state
IS_JRUBY ? [nil, nil] : @engine.ssl_vers_st
end
# used to check the handshake status, in particular when a TCP connection
# Used to check the handshake status, in particular when a TCP connection
# is made with TLSv1.3 as an available protocol
# @version 5.0.0
def bad_tlsv1_3?
HAS_TLS1_3 && @engine.ssl_vers_st == ['TLSv1.3', 'SSLERR']
end
@ -135,14 +138,18 @@ module Puma
alias_method :<<, :write
# This is a temporary fix to deal with websockets code using
# write_nonblock. The problem with implementing it properly
# write_nonblock.
# The problem with implementing it properly
# is that it means we'd have to have the ability to rewind
# an engine because after we write+extract, the socket
# write_nonblock call might raise an exception and later
# code would pass the same data in, but the engine would think
# it had already written the data in. So for the time being
# (and since write blocking is quite rare), go ahead and actually
# block in write_nonblock.
# it had already written the data in.
#
# So for the time being (and since write blocking is quite rare),
# go ahead and actually block in write_nonblock.
#
def write_nonblock(data, *_)
write data
end
@ -258,13 +265,13 @@ module Puma
# disables TLSv1
def no_tlsv1=(tlsv1)
raise ArgumentError, "Invalid value of no_tlsv1" unless ['true', 'false', true, false].include?(tlsv1)
raise ArgumentError, "Invalid value of no_tlsv1=" unless ['true', 'false', true, false].include?(tlsv1)
@no_tlsv1 = tlsv1
end
# disables TLSv1 and TLSv1.1. Overrides `#no_tlsv1=`
def no_tlsv1_1=(tlsv1_1)
raise ArgumentError, "Invalid value of no_tlsv1" unless ['true', 'false', true, false].include?(tlsv1_1)
raise ArgumentError, "Invalid value of no_tlsv1_1=" unless ['true', 'false', true, false].include?(tlsv1_1)
@no_tlsv1_1 = tlsv1_1
end
@ -300,6 +307,7 @@ module Puma
Socket.new io, engine
end
# @version 5.0.0
def addr
@socket.addr
end

View file

@ -29,6 +29,7 @@ module Puma
@events.log str
end
# @version 5.0.0
def stop_control
@control.stop(true) if @control
end
@ -63,6 +64,7 @@ module Puma
@control = control
end
# @version 5.0.0
def close_control_listeners
@control.binder.close_listeners if @control
end

View file

@ -34,7 +34,7 @@ module Puma
attr_reader :thread
attr_reader :events
attr_reader :requests_count
attr_reader :requests_count # @version 5.0.0
attr_accessor :app
attr_accessor :min_threads
@ -97,6 +97,7 @@ module Puma
class << self
# :nodoc:
# @version 5.0.0
def tcp_cork_supported?
RbConfig::CONFIG['host_os'] =~ /linux/ &&
Socket.const_defined?(:IPPROTO_TCP) &&
@ -994,9 +995,11 @@ module Puma
private :possible_header_injection?
# List of methods invoked by #stats.
# @version 5.0.0
STAT_METHODS = [:backlog, :running, :pool_capacity, :max_threads, :requests_count].freeze
# Returns a hash of stats about the running server for reporting purposes.
# @version 5.0.0
def stats
STAT_METHODS.map {|name| [name, send(name) || 0]}.to_h
end

View file

@ -66,7 +66,7 @@ module Puma
attr_reader :spawned, :trim_requested, :waiting
attr_accessor :clean_thread_locals
attr_accessor :out_of_band_hook
attr_accessor :out_of_band_hook # @version 5.0.0
def self.clean_thread_locals
Thread.current.keys.each do |key| # rubocop: disable Performance/HashEachMethods
@ -84,6 +84,7 @@ module Puma
waiting + (@max - spawned)
end
# @version 5.0.0
def busy_threads
with_mutex { @spawned - @waiting + @todo.size }
end
@ -151,6 +152,7 @@ module Puma
private :spawn_thread
# @version 5.0.0
def trigger_out_of_band_hook
return false unless out_of_band_hook && out_of_band_hook.any?
@ -166,6 +168,7 @@ module Puma
private :trigger_out_of_band_hook
# @version 5.0.0
def with_mutex(&block)
@mutex.owned? ?
yield :
@ -231,6 +234,7 @@ module Puma
end
end
# @version 5.0.0
def wait_for_less_busy_worker(delay_s)
# Ruby MRI does GVL, this can result
# in processing contention when multiple threads