Hello community,

here is the log from the commit of package rubygem-puma for openSUSE:Factory 
checked in at 2019-08-16 15:45:15
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-puma (Old)
 and      /work/SRC/openSUSE:Factory/.rubygem-puma.new.22127 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-puma"

Fri Aug 16 15:45:15 2019 rev:33 rq:723544 version:4.1.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/rubygem-puma/rubygem-puma.changes        
2019-08-06 15:10:17.683776855 +0200
+++ /work/SRC/openSUSE:Factory/.rubygem-puma.new.22127/rubygem-puma.changes     
2019-08-16 15:45:19.361705028 +0200
@@ -1,0 +2,30 @@
+Thu Aug 15 13:33:10 UTC 2019 - Manuel Schnitzer <[email protected]>
+
+- updated to version 4.1.0
+
+  * 4 features 
+    * Add REQUEST_PATH on parse error message (#1831)
+    * You can now easily add custom log formatters with the `log_formatter` 
config option (#1816)
+    * Puma.stats now provides process start times (#1844)
+    * Add support for disabling TLSv1.1 (#1836)
+
+  * 7 bugfixes
+    * Fix issue where Puma was creating zombie process entries (#1887)
+    * Fix bugs with line-endings and chunked encoding (#1812)
+    * RACK_URL_SCHEME is now set correctly in all conditions (#1491)
+    * We no longer mutate global STDOUT/STDERR, particularly the sync setting 
(#1837)
+    * SSL read_nonblock no longer blocks (#1857)
+    * Swallow connection errors when sending early hints (#1822)
+    * Backtrace no longer dumped when invalid pumactl commands are run (#1863)
+    
+  * 5 other 
+    * Avoid casting worker_timeout twice (#1838)
+    * Removed a call to private that wasn't doing anything (#1882)
+    * README, Rakefile, docs and test cleanups (#1848, #1847, #1846, #1853, 
#1859, #1850, #1866, #1870, #1872, #1833, #1888)
+    * Puma.io has proper documentation now (https://puma.io/puma/)
+    * Added the Contributor Covenant CoC
+    
+  * 1 known issue 
+    * Some users are still experiencing issues surrounding socket activation 
and Unix sockets (#1842)
+
+-------------------------------------------------------------------

Old:
----
  puma-4.0.1.gem

New:
----
  puma-4.1.0.gem

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rubygem-puma.spec ++++++
--- /var/tmp/diff_new_pack.Pmhwnk/_old  2019-08-16 15:45:21.037704540 +0200
+++ /var/tmp/diff_new_pack.Pmhwnk/_new  2019-08-16 15:45:21.037704540 +0200
@@ -24,7 +24,7 @@
 #
 
 Name:           rubygem-puma
-Version:        4.0.1
+Version:        4.1.0
 Release:        0
 %define mod_name puma
 %define mod_full_name %{mod_name}-%{version}

++++++ puma-4.0.1.gem -> puma-4.1.0.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/History.md new/History.md
--- old/History.md      2019-07-11 19:49:53.000000000 +0200
+++ new/History.md      2019-08-08 21:28:03.000000000 +0200
@@ -6,11 +6,39 @@
 * Bugfixes
   * Your bugfix goes here (#Github Number)
 
+## 4.1.0 / 2019-08-08
+
+* 4 features 
+  * Add REQUEST_PATH on parse error message (#1831)
+  * You can now easily add custom log formatters with the `log_formatter` 
config option (#1816)
+  * Puma.stats now provides process start times (#1844)
+  * Add support for disabling TLSv1.1 (#1836)
+
+* 7 bugfixes
+  * Fix issue where Puma was creating zombie process entries (#1887)
+  * Fix bugs with line-endings and chunked encoding (#1812)
+  * RACK_URL_SCHEME is now set correctly in all conditions (#1491)
+  * We no longer mutate global STDOUT/STDERR, particularly the sync setting 
(#1837)
+  * SSL read_nonblock no longer blocks (#1857)
+  * Swallow connection errors when sending early hints (#1822)
+  * Backtrace no longer dumped when invalid pumactl commands are run (#1863)
+  
+* 5 other 
+  * Avoid casting worker_timeout twice (#1838)
+  * Removed a call to private that wasn't doing anything (#1882)
+  * README, Rakefile, docs and test cleanups (#1848, #1847, #1846, #1853, 
#1859, #1850, #1866, #1870, #1872, #1833, #1888)
+  * Puma.io has proper documentation now (https://puma.io/puma/)
+  * Added the Contributor Covenant CoC
+  
+* 1 known issue 
+  * Some users are still experiencing issues surrounding socket activation and 
Unix sockets (#1842)
+  
 ## 4.0.1 / 2019-07-11
 
 * 2 bugfixes
   * Fix socket removed after reload - should fix problems with systemd socket 
activation. (#1829)
   * Add extconf tests for DTLS_method & TLS_server_method, use in minissl.rb. 
Should fix "undefined symbol: DTLS_method" when compiling against old OpenSSL 
versions. (#1832)
+* 1 other
   * Removed unnecessary RUBY_VERSION checks. (#1827)
 
 ## 4.0.0 / 2019-06-25
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/README.md new/README.md
--- old/README.md       2019-07-11 19:49:53.000000000 +0200
+++ new/README.md       2019-08-08 21:28:03.000000000 +0200
@@ -10,36 +10,38 @@
 [![Code 
Climate](https://codeclimate.com/github/puma/puma.svg)](https://codeclimate.com/github/puma/puma)
 
[![SemVer](https://api.dependabot.com/badges/compatibility_score?dependency-name=puma&package-manager=bundler&version-scheme=semver)](https://dependabot.com/compatibility-score.html?dependency-name=puma&package-manager=bundler&version-scheme=semver)
 
-Puma is a **simple, fast, threaded, and highly concurrent HTTP 1.1 server for 
Ruby/Rack applications** in development and production.
+Puma is a **simple, fast, multi-threaded, and highly concurrent HTTP 1.1 
server for Ruby/Rack applications**.
 
 ## Built For Speed &amp; Concurrency
 
-Under the hood, Puma processes requests using a C-optimized Ragel extension 
(inherited from Mongrel) that provides fast, accurate HTTP 1.1 protocol parsing 
in a portable way. Puma then serves the request in a thread from an internal 
thread pool. Since each request is served in a separate thread, truly 
concurrent Ruby implementations (JRuby, Rubinius) will use all available CPU 
cores.
+Puma processes requests using a C-optimized Ragel extension (inherited from 
Mongrel) that provides fast, accurate HTTP 1.1 protocol parsing in a portable 
way. Puma then serves the request using a thread pool. Each request is served 
in a separate thread, so truly concurrent Ruby implementations (JRuby, 
Rubinius) will use all available CPU cores.
 
 Puma was designed to be the go-to server for [Rubinius](https://rubini.us), 
but also works well with JRuby and MRI.
 
-On MRI, there is a Global VM Lock (GVL) that ensures only one thread can run 
Ruby code at a time. But if you're doing a lot of blocking IO (such as HTTP 
calls to external APIs like Twitter), Puma still improves MRI's throughput by 
allowing blocking IO to be run concurrently.
+On MRI, there is a Global VM Lock (GVL) that ensures only one thread can run 
Ruby code at a time. But if you're doing a lot of blocking IO (such as HTTP 
calls to external APIs like Twitter), Puma still improves MRI's throughput by 
allowing IO waiting to be done in parallel.
 
 ## Quick Start
 
 ```
 $ gem install puma
-$ puma <any rackup (*.ru) file>
+$ puma
 ```
 
+Without arguments, puma will look for a rackup (.ru) file in the current 
working directory called `config.ru`.
+
 ## Frameworks
 
 ### Rails
 
-Puma is the default server for Rails, and should already be included in your 
Gemfile.
+Puma is the default server for Rails, included in the generated Gemfile.
 
-Then start your server with the `rails` command:
+Start your server with the `rails` command:
 
 ```
-$ rails s
+$ rails server
 ```
 
-Many configuration options are not available when using `rails s`. It is 
recommended that you use Puma's executable instead:
+Many configuration options and Puma features are not available when using 
`rails server`. It is recommended that you use Puma's executable instead:
 
 ```
 $ bundle exec puma
@@ -53,7 +55,7 @@
 $ ruby app.rb -s Puma
 ```
 
-Or you can configure your application to always use Puma:
+Or you can configure your Sinatra application to always use Puma:
 
 ```ruby
 require 'sinatra'
@@ -64,6 +66,9 @@
 
 Puma provides numerous options. Consult `puma -h` (or `puma --help`) for a 
full list of CLI options, or see 
[dsl.rb](https://github.com/puma/puma/blob/master/lib/puma/dsl.rb).
 
+You can also find several configuration examples as part of the
+[test](test/config) suite.
+
 ### Thread Pool
 
 Puma uses a thread pool. You can set the minimum and maximum number of threads 
that are available in the pool with the `-t` (or `--threads`) flag:
@@ -72,9 +77,9 @@
 $ puma -t 8:32
 ```
 
-Puma will automatically scale the number of threads, from the minimum until it 
caps out at the maximum, based on how much traffic is present. The current 
default is `0:16`. Feel free to experiment, but be careful not to set the 
number of maximum threads to a large number, as you may exhaust resources on 
the system (or hit resource limits).
+Puma will automatically scale the number of threads, from the minimum until it 
caps out at the maximum, based on how much traffic is present. The current 
default is `0:16`. Feel free to experiment, but be careful not to set the 
number of maximum threads to a large number, as you may exhaust resources on 
the system (or cause contention for the Global VM Lock, when using MRI).
 
-Be aware that additionally Puma creates threads on its own for internal 
purposes (e.g. handling slow clients). So even if you specify -t 1:1, expect 
around 7 threads created in your application.
+Be aware that additionally Puma creates threads on its own for internal 
purposes (e.g. handling slow clients). So, even if you specify -t 1:1, expect 
around 7 threads created in your application.
 
 ### Clustered mode
 
@@ -84,9 +89,9 @@
 $ puma -t 8:32 -w 3
 ```
 
-Note that threads are still used in clustered mode, and the `-t` thread flag 
setting is per worker, so `-w 2 -t 16:16` will spawn 32 threads in total.
+Note that threads are still used in clustered mode, and the `-t` thread flag 
setting is per worker, so `-w 2 -t 16:16` will spawn 32 threads in total, with 
16 in each worker process.
 
-In clustered mode, Puma may "preload" your application. This loads all the 
application code *prior* to forking. Preloading reduces total memory usage of 
your application via an operating system feature called 
[copy-on-write](https://en.wikipedia.org/wiki/Copy-on-write) (Ruby 2.0+ only). 
Use the `--preload` flag from the command line:
+In clustered mode, Puma can "preload" your application. This loads all the 
application code *prior* to forking. Preloading reduces total memory usage of 
your application via an operating system feature called 
[copy-on-write](https://en.wikipedia.org/wiki/Copy-on-write) (Ruby 2.0+ only). 
Use the `--preload` flag from the command line:
 
 ```
 $ puma -w 3 --preload
@@ -111,8 +116,7 @@
 
 This code can be used to setup the process before booting the application, 
allowing
 you to do some Puma-specific things that you don't want to embed in your 
application.
-For instance, you could fire a log notification that a worker booted or send 
something to statsd.
-This can be called multiple times.
+For instance, you could fire a log notification that a worker booted or send 
something to statsd. This can be called multiple times.
 
 If you're preloading your application and using ActiveRecord, it's recommended 
that you setup your connection pool here:
 
@@ -125,7 +129,7 @@
 end
 ```
 
-On top of that, you can specify a block in your configuration file that will 
be run before workers are forked:
+`before_fork` specifies a block to be run before workers are forked:
 
 ```ruby
 # config/puma.rb
@@ -136,15 +140,29 @@
 
 Preloading can’t be used with phased restart, since phased restart kills and 
restarts workers one-by-one, and preload_app copies the code of master into the 
workers.
 
+### Error handling
+
+If puma encounters an error outside of the context of your application, it 
will respond with a 500 and a simple
+textual error message (see `lowlevel_error` in [this 
file](https://github.com/puma/puma/blob/master/lib/puma/server.rb)).
+You can specify custom behavior for this scenario. For example, you can report 
the error to your third-party
+error-tracking service (in this example, [rollbar](http://rollbar.com)):
+
+```ruby
+lowlevel_error_handler do |e|
+  Rollbar.critical(e)
+  [500, {}, ["An error has occurred, and engineers have been informed. Please 
reload the page. If you continue to have problems, contact 
[email protected]\n"]]
+end
+```
+
 ### Binding TCP / Sockets
 
-In contrast to many other server configs which require multiple flags, Puma 
simply uses one URI parameter with the `-b` (or `--bind`) flag:
+Bind Puma to a socket with the `-b` (or `--bind`) flag:
 
 ```
 $ puma -b tcp://127.0.0.1:9292
 ```
 
-Want to use UNIX Sockets instead of TCP (which can provide a 5-10% performance 
boost)?
+To use a UNIX Socket instead of TCP:
 
 ```
 $ puma -b unix:///var/run/puma.sock
@@ -157,13 +175,14 @@
 ```
 
 Need a bit of security? Use SSL sockets:
+
 ```
 $ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert'
 ```
 
 #### Controlling SSL Cipher Suites
 
-Need to use or avoid specific SSL cipher suites? Use `ssl_cipher_filter` or 
`ssl_cipher_list` options.
+To use or avoid specific SSL cipher suites, use `ssl_cipher_filter` or 
`ssl_cipher_list` options.
 
 ##### Ruby:
 
@@ -179,7 +198,7 @@
 
 See https://www.openssl.org/docs/man1.0.2/apps/ciphers.html for cipher filter 
format and full list of cipher suites.
 
-Don't want to use insecure TLSv1.0 ?
+Disable TLS v1 with the `no_tlsv1` option:
 
 ```
 $ puma -b 
'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&no_tlsv1=true'
@@ -187,13 +206,13 @@
 
 ### Control/Status Server
 
-Puma has a built-in status/control app that can be used to query and control 
Puma itself.
+Puma has a built-in status and control app that can be used to query and 
control Puma.
 
 ```
 $ puma --control-url tcp://127.0.0.1:9293 --control-token foo
 ```
 
-Puma will start the control server on localhost port 9293. All requests to the 
control server will need to include `token=foo` as a query parameter. This 
allows for simple authentication. Check out 
[status.rb](https://github.com/puma/puma/blob/master/lib/puma/app/status.rb) to 
see what the app has available.
+Puma will start the control server on localhost port 9293. All requests to the 
control server will need to include control token (in this case, `token=foo`) 
as a query parameter. This allows for simple authentication. Check out 
[status.rb](https://github.com/puma/puma/blob/master/lib/puma/app/status.rb) to 
see what the status app has available.
 
 You can also interact with the control server via `pumactl`. This command will 
restart Puma:
 
@@ -205,13 +224,13 @@
 
 ### Configuration File
 
-You can also provide a configuration file which Puma will use with the `-C` 
(or `--config`) flag:
+You can also provide a configuration file with the `-C` (or `--config`) flag:
 
 ```
 $ puma -C /path/to/config
 ```
 
-If no configuration file is specified, Puma will look for a configuration file 
at `config/puma.rb`. If an environment is specified, either via the `-e` and 
`--environment` flags, or through the `RACK_ENV` environment variable, the 
default file location will be `config/puma/environment_name.rb`.
+If no configuration file is specified, Puma will look for a configuration file 
at `config/puma.rb`. If an environment is specified, either via the `-e` and 
`--environment` flags, or through the `RACK_ENV` environment variable, Puma 
looks for configuration at `config/puma/<environment_name>.rb`.
 
 If you want to prevent Puma from looking for a configuration file in those 
locations, provide a dash as the argument to the `-C` (or `--config`) flag:
 
@@ -219,7 +238,7 @@
 $ puma -C "-"
 ```
 
-Take the following [sample 
configuration](https://github.com/puma/puma/blob/master/examples/config.rb) as 
inspiration or check out 
[dsl.rb](https://github.com/puma/puma/blob/master/lib/puma/dsl.rb) to see all 
available options.
+Check out [dsl.rb](https://github.com/puma/puma/blob/master/lib/puma/dsl.rb) 
to see all available options.
 
 ## Restart
 
@@ -236,7 +255,7 @@
 Some platforms do not support all Puma features.
 
   * **JRuby**, **Windows**: server sockets are not seamless on restart, they 
must be closed and reopened. These platforms have no way to pass descriptors 
into a new process that is exposed to Ruby. Also, cluster mode is not supported 
due to a lack of fork(2).
-  * **Windows**: daemon mode is not supported due to a lack of fork(2).
+  * **Windows**: Cluster mode is not supported due to a lack of fork(2).
 
 ## Known Bugs
 
@@ -278,6 +297,24 @@
 $ bundle exec rake
 ```
 
+To run a single test file, use the `TEST` environment variable:
+
+```bash
+$ TEST=test/test_binder.rb bundle exec rake test
+```
+
+Or use [`m`](https://github.com/qrush/m):
+
+```
+$ bundle exec m test/test_binder.rb
+```
+
+Which can also be used to run a single test case:
+
+```
+$ bundle exec m test/test_binder.rb:37
+```
+
 ## License
 
 Puma is copyright Evan Phoenix and contributors, licensed under the BSD 
3-Clause license. See the included LICENSE file for details.
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ext/puma_http11/mini_ssl.c 
new/ext/puma_http11/mini_ssl.c
--- old/ext/puma_http11/mini_ssl.c      2019-07-11 19:49:53.000000000 +0200
+++ new/ext/puma_http11/mini_ssl.c      2019-08-08 21:28:03.000000000 +0200
@@ -142,7 +142,7 @@
   VALUE obj;
   SSL_CTX* ctx;
   SSL* ssl;
-  int ssl_options;
+  int min, ssl_options;
 
   ms_conn* conn = engine_alloc(self, &obj);
 
@@ -168,6 +168,9 @@
   ID sym_no_tlsv1 = rb_intern("no_tlsv1");
   VALUE no_tlsv1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1, 0);
 
+  ID sym_no_tlsv1_1 = rb_intern("no_tlsv1_1");
+  VALUE no_tlsv1_1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1_1, 0);
+
 #ifdef HAVE_TLS_SERVER_METHOD
   ctx = SSL_CTX_new(TLS_server_method());
 #else
@@ -183,12 +186,36 @@
     SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL);
   }
 
-  ssl_options  = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_NO_SSLv2 | 
SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE | 
SSL_OP_NO_COMPRESSION;
+  ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | 
SSL_OP_NO_COMPRESSION;
 
-  if(RTEST(no_tlsv1)) {
+#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
+  if (RTEST(no_tlsv1_1)) {
+    min = TLS1_2_VERSION;
+  }
+  else if (RTEST(no_tlsv1)) {
+    min = TLS1_1_VERSION;
+  }
+  else {
+    min = TLS1_VERSION;
+  }
+  
+  SSL_CTX_set_min_proto_version(ctx, min);
+
+  SSL_CTX_set_options(ctx, ssl_options);
+
+#else
+  /* As of 1.0.2f, SSL_OP_SINGLE_DH_USE key use is always on */
+  ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE;
+
+  if (RTEST(no_tlsv1)) {
     ssl_options |= SSL_OP_NO_TLSv1;
   }
+  if(RTEST(no_tlsv1_1)) {
+    ssl_options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
+  }
   SSL_CTX_set_options(ctx, ssl_options);
+#endif
+
   SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
 
   if (!NIL_P(ssl_cipher_filter)) {
@@ -458,14 +485,35 @@
   // OpenSSL Build / Runtime/Load versions
 
   /* Version of OpenSSL that Puma was compiled with */
-       rb_define_const(mod, "OPENSSL_VERSION", 
rb_str_new2(OPENSSL_VERSION_TEXT));
+  rb_define_const(mod, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
 
 #if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
-       /* Version of OpenSSL that Puma loaded with */
-       rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", 
rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
+  /* Version of OpenSSL that Puma loaded with */
+  rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", 
rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
 #else
-       rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", 
rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
+  rb_define_const(mod, "OPENSSL_LIBRARY_VERSION", 
rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
 #endif
+ 
+#if defined(OPENSSL_NO_SSL3) || defined(OPENSSL_NO_SSL3_METHOD) 
+  /* True if SSL3 is not available */ 
+  rb_define_const(mod, "OPENSSL_NO_SSL3", Qtrue); 
+#else 
+  rb_define_const(mod, "OPENSSL_NO_SSL3", Qfalse); 
+#endif 
+
+#if defined(OPENSSL_NO_TLS1) || defined(OPENSSL_NO_TLS1_METHOD) 
+  /* True if TLS1 is not available */ 
+  rb_define_const(mod, "OPENSSL_NO_TLS1", Qtrue); 
+#else 
+  rb_define_const(mod, "OPENSSL_NO_TLS1", Qfalse); 
+#endif 
+
+#if defined(OPENSSL_NO_TLS1_1) || defined(OPENSSL_NO_TLS1_1_METHOD) 
+  /* True if TLS1_1 is not available */ 
+  rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qtrue); 
+#else 
+  rb_define_const(mod, "OPENSSL_NO_TLS1_1", Qfalse); 
+#endif 
 
   rb_define_singleton_method(mod, "check", noop, 0);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ext/puma_http11/org/jruby/puma/MiniSSL.java 
new/ext/puma_http11/org/jruby/puma/MiniSSL.java
--- old/ext/puma_http11/org/jruby/puma/MiniSSL.java     2019-07-11 
19:49:53.000000000 +0200
+++ new/ext/puma_http11/org/jruby/puma/MiniSSL.java     2019-08-08 
21:28:03.000000000 +0200
@@ -166,6 +166,10 @@
         protocols = new String[] { "TLSv1", "TLSv1.1", "TLSv1.2" };
     }
 
+    if(miniSSLContext.callMethod(threadContext, "no_tlsv1_1").isTrue()) {
+        protocols = new String[] { "TLSv1.2" };
+    }
+
     engine.setEnabledProtocols(protocols);
     engine.setUseClientMode(false);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/accept_nonblock.rb 
new/lib/puma/accept_nonblock.rb
--- old/lib/puma/accept_nonblock.rb     2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/accept_nonblock.rb     2019-08-08 21:28:03.000000000 +0200
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 require 'openssl'
 
 module OpenSSL
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/app/status.rb new/lib/puma/app/status.rb
--- old/lib/puma/app/status.rb  2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/app/status.rb  2019-08-08 21:28:03.000000000 +0200
@@ -1,7 +1,11 @@
+# frozen_string_literal: true
+
 require 'json'
 
 module Puma
   module App
+    # Check out {#call}'s source code to see what actions this web application
+    # can respond to.
     class Status
       def initialize(cli)
         @cli = cli
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/binder.rb new/lib/puma/binder.rb
--- old/lib/puma/binder.rb      2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/binder.rb      2019-08-08 21:28:03.000000000 +0200
@@ -195,6 +195,7 @@
           end
 
           ctx.no_tlsv1 = true if params['no_tlsv1'] == 'true'
+          ctx.no_tlsv1_1 = true if params['no_tlsv1_1'] == 'true'
 
           if params['verify_mode']
             ctx.verify_mode = case params['verify_mode']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/client.rb new/lib/puma/client.rb
--- old/lib/puma/client.rb      2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/client.rb      2019-08-08 21:28:03.000000000 +0200
@@ -68,6 +68,8 @@
       @remote_addr_header = nil
 
       @body_remain = 0
+
+      @in_last_chunk = false
     end
 
     attr_reader :env, :to_io, :body, :io, :timeout_at, :ready, :hijacked,
@@ -108,6 +110,7 @@
       @ready = false
       @body_remain = 0
       @peerip = nil
+      @in_last_chunk = false
 
       if @buffer
         @parsed_bytes = @parser.execute(@env, @buffer, @parsed_bytes)
@@ -166,7 +169,7 @@
           chunk = chunk[@partial_part_left..-1]
           @partial_part_left = 0
         else
-          @body << chunk
+          @body << chunk if @partial_part_left > 2 # don't include the last 
\r\n
           @partial_part_left -= chunk.size
           return false
         end
@@ -184,12 +187,20 @@
         if line.end_with?("\r\n")
           len = line.strip.to_i(16)
           if len == 0
+            @in_last_chunk = true
             @body.rewind
             rest = io.read
-            rest = rest[2..-1] if rest.start_with?("\r\n")
-            @buffer = rest.empty? ? nil : rest
-            set_ready
-            return true
+            last_crlf_size = "\r\n".bytesize
+            if rest.bytesize < last_crlf_size
+              @buffer = nil
+              @partial_part_left = last_crlf_size - rest.bytesize
+              return false
+            else
+              @buffer = rest[last_crlf_size..-1]
+              @buffer = nil if @buffer.empty?
+              set_ready
+              return true
+            end
           end
 
           len += 2
@@ -219,7 +230,12 @@
         end
       end
 
-      return false
+      if @in_last_chunk
+        set_ready
+        true
+      else
+        false
+      end
     end
 
     def read_chunked_body
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/cluster.rb new/lib/puma/cluster.rb
--- old/lib/puma/cluster.rb     2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/cluster.rb     2019-08-08 21:28:03.000000000 +0200
@@ -95,12 +95,13 @@
         @signal = "TERM"
         @options = options
         @first_term_sent = nil
+        @started_at = Time.now
         @last_checkin = Time.now
         @last_status = '{}'
         @dead = false
       end
 
-      attr_reader :index, :pid, :phase, :signal, :last_checkin, :last_status
+      attr_reader :index, :pid, :phase, :signal, :last_checkin, :last_status, 
:started_at
 
       def booted?
         @stage == :booted
@@ -226,9 +227,11 @@
       # during this loop by giving the kernel time to kill them.
       sleep 1 if any
 
-      @workers.reject! { |w| Process.waitpid(w.pid, Process::WNOHANG) }
-
-      @workers.reject!(&:dead?)
+      pids = []
+      while pid = Process.waitpid(-1, Process::WNOHANG) do
+        pids << pid
+      end
+      @workers.reject! { |w| w.dead? || pids.include?(w.pid) }
 
       cull_workers
       spawn_workers
@@ -376,8 +379,8 @@
     def stats
       old_worker_count = @workers.count { |w| w.phase != @phase }
       booted_worker_count = @workers.count { |w| w.booted? }
-      worker_status = '[' + @workers.map { |w| %Q!{ "pid": #{w.pid}, "index": 
#{w.index}, "phase": #{w.phase}, "booted": #{w.booted?}, "last_checkin": 
"#{w.last_checkin.utc.iso8601}", "last_status": #{w.last_status} }!}.join(",") 
+ ']'
-      %Q!{ "workers": #{@workers.size}, "phase": #{@phase}, "booted_workers": 
#{booted_worker_count}, "old_workers": #{old_worker_count}, "worker_status": 
#{worker_status} }!
+      worker_status = '[' + @workers.map { |w| %Q!{ "started_at": 
"#{w.started_at.utc.iso8601}", "pid": #{w.pid}, "index": #{w.index}, "phase": 
#{w.phase}, "booted": #{w.booted?}, "last_checkin": 
"#{w.last_checkin.utc.iso8601}", "last_status": #{w.last_status} }!}.join(",") 
+ ']'
+      %Q!{ "started_at": "#{@started_at.utc.iso8601}", "workers": 
#{@workers.size}, "phase": #{@phase}, "booted_workers": #{booted_worker_count}, 
"old_workers": #{old_worker_count}, "worker_status": #{worker_status} }!
     end
 
     def preload?
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/configuration.rb 
new/lib/puma/configuration.rb
--- old/lib/puma/configuration.rb       2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/configuration.rb       2019-08-08 21:28:03.000000000 +0200
@@ -20,7 +20,7 @@
   # In this class any "user" specified options take precedence over any
   # "file" specified options, take precedence over any "default" options.
   #
-  # User input is prefered over "defaults":
+  # User input is preferred over "defaults":
   #   user_options    = { foo: "bar" }
   #   default_options = { foo: "zoo" }
   #   options = UserFileDefaultOptions.new(user_options, default_options)
@@ -32,7 +32,7 @@
   #   puts options.all_of(:foo)
   #   # => ["bar", "zoo"]
   #
-  # A "file" option can be set. This config will be prefered over "default" 
options
+  # A "file" option can be set. This config will be preferred over "default" 
options
   # but will defer to any available "user" specified options.
   #
   #   user_options    = { foo: "bar" }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/const.rb new/lib/puma/const.rb
--- old/lib/puma/const.rb       2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/const.rb       2019-08-08 21:28:03.000000000 +0200
@@ -100,8 +100,8 @@
   # too taxing on performance.
   module Const
 
-    PUMA_VERSION = VERSION = "4.0.1".freeze
-    CODE_NAME = "4 Fast 4 Furious".freeze
+    PUMA_VERSION = VERSION = "4.1.0".freeze
+    CODE_NAME = "Fourth and One".freeze
     PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
 
     FAST_TRACK_KA_TIMEOUT = 0.2
@@ -160,6 +160,9 @@
     LINE_END = "\r\n".freeze
     REMOTE_ADDR = "REMOTE_ADDR".freeze
     HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR".freeze
+    HTTP_X_FORWARDED_SSL = "HTTP_X_FORWARDED_SSL".freeze
+    HTTP_X_FORWARDED_SCHEME = "HTTP_X_FORWARDED_SCHEME".freeze
+    HTTP_X_FORWARDED_PROTO = "HTTP_X_FORWARDED_PROTO".freeze
 
     SERVER_NAME = "SERVER_NAME".freeze
     SERVER_PORT = "SERVER_PORT".freeze
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/control_cli.rb new/lib/puma/control_cli.rb
--- old/lib/puma/control_cli.rb 2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/control_cli.rb 2019-08-08 21:28:03.000000000 +0200
@@ -101,7 +101,6 @@
 
     rescue => e
       @stdout.puts e.message
-      @stdout.puts e.backtrace
       exit 1
     end
 
@@ -244,7 +243,6 @@
 
     rescue => e
       message e.message
-      message e.backtrace
       exit 1
     end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/dsl.rb new/lib/puma/dsl.rb
--- old/lib/puma/dsl.rb 2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/dsl.rb 2019-08-08 21:28:03.000000000 +0200
@@ -3,7 +3,7 @@
 require 'puma/const'
 
 module Puma
-  # The methods that are available for use inside the config file.
+  # The methods that are available for use inside the configuration file.
   # These same methods are used in Puma cli and the rack handler
   # internally.
   #
@@ -28,7 +28,8 @@
   #   puts config.options[:binds]
   #   # => "tcp://127.0.0.1:3002"
   #
-  # Detailed docs can be found in `examples/config.rb`
+  # You can also find many examples being used by the test suite in
+  # +test/config+.
   class DSL
     include ConfigDefault
 
@@ -81,9 +82,22 @@
       @plugins << @config.load_plugin(name)
     end
 
-    # Use +obj+ or +block+ as the Rack app. This allows a config file to
-    # be the app itself.
+    # Use an object or block as the rack application. This allows the
+    # configuration file to be the application itself.
     #
+    # @example
+    #   app do |env|
+    #     body = 'Hello, World!'
+    #
+    #     [
+    #       200,
+    #       {
+    #         'Content-Type' => 'text/plain',
+    #         'Content-Length' => body.length.to_s
+    #       },
+    #       [body]
+    #     ]
+    #   end
     def app(obj=nil, &block)
       obj ||= block
 
@@ -92,9 +106,20 @@
       @options[:app] = obj
     end
 
-    # Start the Puma control rack app on +url+. This app can be communicated
-    # with to control the main server.
-    #
+    # Start the Puma control rack application on +url+. This application can
+    # be communicated with to control the main server. Additionally, you can
+    # provide an authentication token, so all requests to the control server
+    # will need to include that token as a query parameter. This allows for
+    # simple authentication.
+    #
+    # Check out {Puma::App::Status} to see what the app has available.
+    #
+    # @example
+    #   activate_control_app 'unix:///var/run/pumactl.sock'
+    # @example
+    #   activate_control_app 'unix:///var/run/pumactl.sock', { auth_token: 
'12345' }
+    # @example
+    #   activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true }
     def activate_control_app(url="auto", opts={})
       if url == "auto"
         path = Configuration.temp_path
@@ -127,22 +152,29 @@
       @options[:config_files] << file
     end
 
-    # Adds a binding for the server to +url+. tcp://, unix://, and ssl:// are 
the only accepted
-    # protocols. Use query parameters within the url to specify options.
-    #
-    # @note multiple urls can be bound to, calling `bind` does not overwrite 
previous bindings.
-    #
-    # @example Explicitly the socket backlog depth (default is 1024)
-    #   bind('unix:///var/run/puma.sock?backlog=2048')
-    #
-    # @example Set up ssl cert
-    #   bind('ssl://127.0.0.1:9292?key=key.key&cert=cert.pem')
-    #
-    # @example Prefer low-latency over higher throughput (via 
`Socket::TCP_NODELAY`)
-    #   bind('tcp://0.0.0.0:9292?low_latency=true')
-    #
-    # @example Set socket permissions
-    #   bind('unix:///var/run/puma.sock?umask=0111')
+    # Bind the server to +url+. "tcp://", "unix://" and "ssl://" are the only
+    # accepted protocols. Multiple urls can be bound to, calling `bind` does
+    # not overwrite previous bindings.
+    #
+    # The default is "tcp://0.0.0.0:9292".
+    #
+    # 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+.
+    #
+    # @example Backlog depth
+    #   bind 'unix:///var/run/puma.sock?backlog=512'
+    # @example SSL cert
+    #   bind 'ssl://127.0.0.1:9292?key=key.key&cert=cert.pem'
+    # @example Disable optimization for low latency
+    #   bind 'tcp://0.0.0.0:9292?low_latency=false'
+    # @example Socket permissions
+    #   bind 'unix:///var/run/puma.sock?umask=0111'
     def bind(url)
       @options[:binds] ||= []
       @options[:binds] << url
@@ -154,33 +186,40 @@
 
     # Define the TCP port to bind to. Use +bind+ for more advanced options.
     #
+    # @example
+    #   port 9292
     def port(port, host=nil)
       host ||= default_host
       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.
     def persistent_timeout(seconds)
       @options[:persistent_timeout] = Integer(seconds)
     end
 
-    # Define how long the tcp socket stays open, if no data has been received
-    #
+    # Define how long the tcp socket stays open, if no data has been received.
     def first_data_timeout(seconds)
       @options[:first_data_timeout] = Integer(seconds)
     end
 
     # Work around leaky apps that leave garbage in Thread locals
-    # across requests
-    #
+    # across requests.
     def clean_thread_locals(which=true)
       @options[:clean_thread_locals] = which
     end
 
-    # Daemonize the server into the background. Highly suggest that
-    # this be combined with +pidfile+ and +stdout_redirect+.
+    # Daemonize the server into the background. It's highly recommended to
+    # use this in combination with +pidfile+ and +stdout_redirect+.
+    #
+    # The default is "false".
+    #
+    # @example
+    #   daemonize
+    #
+    # @example
+    #   daemonize false
     def daemonize(which=true)
       @options[:daemon] = which
     end
@@ -193,7 +232,13 @@
       @options[:drain_on_shutdown] = which
     end
 
-    # Set the environment in which the Rack's app will run.
+    # Set the environment in which the rack's app will run. The value must be
+    # a string.
+    #
+    # The default is "development".
+    #
+    # @example
+    #   environment 'production'
     def environment(environment)
       @options[:environment] = environment
     end
@@ -219,30 +264,41 @@
     end
 
     # Code to run before doing a restart. This code should
-    # close logfiles, database connections, etc.
+    # close log files, database connections, etc.
     #
     # This can be called multiple times to add code each time.
     #
+    # @example
+    #   on_restart do
+    #     puts 'On restart...'
+    #   end
     def on_restart(&block)
       @options[:on_restart] ||= []
       @options[:on_restart] << block
     end
 
-    # Command to use to restart puma. This should be just how to
-    # load puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
-    # to puma, as those are the same as the original process.
+    # Command to use to restart Puma. This should be just how to
+    # load Puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
+    # to Puma, as those are the same as the original process.
     #
+    # @example
+    #   restart_command '/u/app/lolcat/bin/restart_puma'
     def restart_command(cmd)
       @options[:restart_cmd] = cmd.to_s
     end
 
-    # Store the pid of the server in the file at +path+.
+    # Store the pid of the server in the file at "path".
+    #
+    # @example
+    #   pidfile '/u/apps/lolcat/tmp/pids/puma.pid'
     def pidfile(path)
       @options[:pidfile] = path.to_s
     end
 
-    # Disable request logging.
+    # Disable request logging, if this isn't used it'll be enabled by default.
     #
+    # @example
+    #   quiet
     def quiet(which=true)
       @options[:log_requests] = !which
     end
@@ -261,6 +317,10 @@
 
     # Load +path+ as a rackup file.
     #
+    # The default is "config.ru".
+    #
+    # @example
+    #   rackup '/u/apps/lolcat/config.ru'
     def rackup(path)
       @options[:rackup] = path.to_s
     end
@@ -275,16 +335,32 @@
       @options[:early_hints] = answer
     end
 
-    # Redirect STDOUT and STDERR to files specified.
+    # Redirect STDOUT and STDERR to files specified. The +append+ parameter
+    # specifies whether the output is appended, the default is +false+.
+    #
+    # @example
+    #   stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr'
+    # @example
+    #   stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr', 
true
     def stdout_redirect(stdout=nil, stderr=nil, append=false)
       @options[:redirect_stdout] = stdout
       @options[:redirect_stderr] = stderr
       @options[:redirect_append] = append
     end
 
+    def log_formatter(&block)
+      @options[:log_formatter] = block
+    end
+
     # Configure +min+ to be the minimum number of threads to use to answer
     # requests and +max+ the maximum.
     #
+    # The default is "0, 16".
+    #
+    # @example
+    #   threads 0, 16
+    # @example
+    #   threads 5, 5
     def threads(min, max)
       min = Integer(min)
       max = Integer(max)
@@ -300,84 +376,135 @@
       @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.
+    #
+    # @example
+    #   ssl_bind '127.0.0.1', '9292', {
+    #     cert: path_to_cert,
+    #     key: path_to_key,
+    #     ssl_cipher_filter: cipher_filter, # optional
+    #     verify_mode: verify_mode,         # default 'none'
+    #   }
+    # @example For JRuby additional keys are required: keystore & 
keystore_pass.
+    #   ssl_bind '127.0.0.1', '9292', {
+    #     cert: path_to_cert,
+    #     key: path_to_key,
+    #     ssl_cipher_filter: cipher_filter, # optional
+    #     verify_mode: verify_mode,         # default 'none'
+    #     keystore: path_to_keystore,
+    #     keystore_pass: password
+    #   }
     def ssl_bind(host, port, opts)
       verify = opts.fetch(:verify_mode, 'none')
       no_tlsv1 = opts.fetch(:no_tlsv1, 'false')
+      no_tlsv1_1 = opts.fetch(:no_tlsv1_1, 'false')
       ca_additions = "&ca=#{opts[:ca]}" if ['peer', 
'force_peer'].include?(verify)
 
       if defined?(JRUBY_VERSION)
         keystore_additions = 
"keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
-        bind 
"ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}&verify_mode=#{verify}&no_tlsv1=#{no_tlsv1}#{ca_additions}"
+        bind 
"ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}&verify_mode=#{verify}&no_tlsv1=#{no_tlsv1}&no_tlsv1_1=#{no_tlsv1_1}#{ca_additions}"
       else
         ssl_cipher_filter = "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" 
if opts[:ssl_cipher_filter]
-        bind 
"ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}#{ssl_cipher_filter}&verify_mode=#{verify}&no_tlsv1=#{no_tlsv1}#{ca_additions}"
+        bind 
"ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}#{ssl_cipher_filter}&verify_mode=#{verify}&no_tlsv1=#{no_tlsv1}&no_tlsv1_1=#{no_tlsv1_1}#{ca_additions}"
       end
     end
 
     # Use +path+ as the file to store the server info state. This is
-    # used by pumactl to query and control the server.
+    # used by +pumactl+ to query and control the server.
     #
+    # @example
+    #   state_path '/u/apps/lolcat/tmp/pids/puma.state'
     def state_path(path)
       @options[:state] = path.to_s
     end
 
-    # *Cluster mode only* How many worker processes to run.
+    # How many worker processes to run.  Typically this is set to
+    # to the number of available cores.
+    #
+    # The default is 0.
     #
+    # @note Cluster mode only.
     def workers(count)
       @options[:workers] = count.to_i
     end
 
-    # *Cluster mode only* Code to run immediately before master process
+    # Code to run immediately before master process
     # forks workers (once on boot). These hooks can block if necessary
-    # to wait for background operations unknown to puma to finish before
+    # to wait for background operations unknown to Puma to finish before
     # the process terminates.
-    # This can be used to close any connections to remote servers (database, 
redis, ...)
-    # that were opened when preloading the code
+    # This can be used to close any connections to remote servers (database,
+    # Redis, ...) that were opened when preloading the code.
     #
-    # This can be called multiple times to add hooks.
+    # This can be called multiple times to add several hooks.
     #
+    # @note Cluster mode only.
+    # @example
+    #   before_fork do
+    #     puts "Starting workers..."
+    #   end
     def before_fork(&block)
       @options[:before_fork] ||= []
       @options[:before_fork] << block
     end
 
-    # *Cluster mode only* Code to run in a worker when it boots to setup
+    # Code to run in a worker when it boots to setup
     # the process before booting the app.
     #
-    # This can be called multiple times to add hooks.
+    # This can be called multiple times to add several hooks.
     #
+    # @note Cluster mode only.
+    # @example
+    #   on_worker_fork do
+    #     puts 'Before worker fork...'
+    #   end
     def on_worker_boot(&block)
       @options[:before_worker_boot] ||= []
       @options[:before_worker_boot] << block
     end
 
-    # *Cluster mode only* Code to run immediately before a worker shuts
+    # Code to run immediately before a worker shuts
     # down (after it has finished processing HTTP requests). These hooks
     # can block if necessary to wait for background operations unknown
-    # to puma to finish before the process terminates.
+    # to Puma to finish before the process terminates.
     #
-    # This can be called multiple times to add hooks.
+    # This can be called multiple times to add several hooks.
     #
+    # @note Cluster mode only.
+    # @example
+    #   on_worker_shutdown do
+    #     puts 'On worker shutdown...'
+    #   end
     def on_worker_shutdown(&block)
       @options[:before_worker_shutdown] ||= []
       @options[:before_worker_shutdown] << block
     end
 
-    # *Cluster mode only* Code to run in the master when it is
-    # about to create the worker by forking itself.
+    # Code to run in the master right before a worker is started. The worker's
+    # index is passed as an argument.
     #
-    # This can be called multiple times to add hooks.
+    # This can be called multiple times to add several hooks.
     #
+    # @note Cluster mode only.
+    # @example
+    #   on_worker_fork do
+    #     puts 'Before worker fork...'
+    #   end
     def on_worker_fork(&block)
       @options[:before_worker_fork] ||= []
       @options[:before_worker_fork] << block
     end
 
-    # *Cluster mode only* Code to run in the master after it starts
-    # a worker.
+    # Code to run in the master after a worker has been started. The worker's
+    # index is passed as an argument.
     #
-    # This can be called multiple times to add hooks.
+    # This is called everytime a worker is to be started.
     #
+    # @note Cluster mode only.
+    # @example
+    #   after_worker_fork do
+    #     puts 'After worker fork...'
+    #   end
     def after_worker_fork(&block)
       @options[:after_worker_fork] ||= []
       @options[:after_worker_fork] = block
@@ -393,14 +520,18 @@
     # This hook is useful for running out-of-band garbage collection
     # or scheduling asynchronous tasks to execute after a response.
     #
-    # This can be called multiple times to add hooks.
-    #
+    # This can be called multiple times to add several hooks.
     def out_of_band(&block)
       @options[:out_of_band] ||= []
       @options[:out_of_band] << block
     end
 
     # The directory to operate out of.
+    #
+    # The default is the current directory.
+    #
+    # @example
+    #   directory '/u/apps/lolcat'
     def directory(dir)
       @options[:directory] = dir.to_s
     end
@@ -411,22 +542,28 @@
       directory dir
     end
 
-    # Run the app as a raw TCP app instead of an HTTP rack app
+    # Run the app as a raw TCP app instead of an HTTP rack app.
     def tcp_mode
       @options[:mode] = :tcp
     end
 
-    # *Cluster mode only* Preload the application before starting
-    # the workers and setting up the listen ports. This conflicts
-    # with using the phased restart feature, you can't use both.
+    # Preload the application before starting the workers; this conflicts with
+    # phased restart feature. This is off by default.
     #
+    # @note Cluster mode only.
+    # @example
+    #   preload_app!
     def preload_app!(answer=true)
       @options[:preload_app] = answer
     end
 
-    # Use +obj+ or +block+ as the low level error handler. This allows a 
config file to
-    # change the default error on the server.
+    # Use +obj+ or +block+ as the low level error handler. This allows the
+    # configuration file to change the default error on the server.
     #
+    # @example
+    #   lowlevel_error_handler do |err|
+    #     [200, {}, ["error page"]]
+    #   end
     def lowlevel_error_handler(obj=nil, &block)
       obj ||= block
       raise "Provide either a #call'able or a block" unless obj
@@ -436,38 +573,57 @@
     # This option is used to allow your app and its gems to be
     # properly reloaded when not using preload.
     #
-    # When set, if puma detects that it's been invoked in the
+    # When set, if Puma detects that it's been invoked in the
     # context of Bundler, it will cleanup the environment and
     # re-run itself outside the Bundler environment, but directly
     # using the files that Bundler has setup.
     #
-    # This means that puma is now decoupled from your Bundler
+    # This means that Puma is now decoupled from your Bundler
     # context and when each worker loads, it will be loading a
     # new Bundler context and thus can float around as the release
     # dictates.
+    #
+    # @note This is incompatible with +preload_app!+.
     def prune_bundler(answer=true)
       @options[:prune_bundler] = answer
     end
 
-    # In environments where SIGTERM is something expected, instructing
-    # puma to shutdown gracefully ( for example in Kubernetes, where
-    # rolling restart is guaranteed usually on infrastructure level )
-    # SignalException should not be raised for SIGTERM
+    # By default, Puma will raise SignalException when SIGTERM is received. In
+    # environments where SIGTERM is something expected, you can suppress these
+    # with this option.
     #
-    # When set to false, if puma process receives SIGTERM, it won't raise 
SignalException
+    # This can be useful for example in Kubernetes, where rolling restart is
+    # guaranteed usually on infrastructure level.
+    #
+    # @example
+    #   raise_exception_on_sigterm false
     def raise_exception_on_sigterm(answer=true)
       @options[:raise_exception_on_sigterm] = answer
     end
 
-    # Additional text to display in process listing
+    # Additional text to display in process listing.
+    #
+    # If you do not specify a tag, Puma will infer it. If you do not want Puma
+    # to add a tag, use an empty string.
+    #
+    # @example
+    #   tag 'app name'
+    # @example
+    #   tag ''
     def tag(string)
       @options[:tag] = string.to_s
     end
 
-    # *Cluster mode only* Set the timeout for workers in seconds
-    # When set the master process will terminate any workers
-    # that have not checked in within the given +timeout+.
-    # This mitigates hung processes. Default value is 60 seconds.
+    # Verifies that all workers have checked in to the master process within
+    # the given timeout. If not the worker process will be restarted. This is
+    # not a request timeout, it is to protect against a hung or dead process.
+    # Setting this value will not protect against slow requests.
+    #
+    # The minimum value is 6 seconds, the default value is 60 seconds.
+    #
+    # @note Cluster mode only.
+    # @example
+    #   worker_timeout 60
     def worker_timeout(timeout)
       timeout = Integer(timeout)
       min = Const::WORKER_CHECK_INTERVAL
@@ -476,15 +632,23 @@
         raise "The minimum worker_timeout must be greater than the worker 
reporting interval (#{min})"
       end
 
-      @options[:worker_timeout] = Integer(timeout)
+      @options[:worker_timeout] = timeout
     end
 
-    # *Cluster mode only* Set the timeout for workers to boot
+    # Change the default worker timeout for booting.
+    #
+    # If unspecified, this defaults to the value of worker_timeout.
+    #
+    # @note Cluster mode only.
+    # @example:
+    #   worker_boot_timeout 60
     def worker_boot_timeout(timeout)
       @options[:worker_boot_timeout] = Integer(timeout)
     end
 
-    # *Cluster mode only* Set the timeout for worker shutdown
+    # Set the timeout for worker shutdown
+    #
+    # @note Cluster mode only.
     def worker_shutdown_timeout(timeout)
       @options[:worker_shutdown_timeout] = Integer(timeout)
     end
@@ -501,7 +665,7 @@
     # Note that setting this to false disables HTTP keepalive and
     # 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.
+    # slow clients and queue requests before they reach Puma.
     def queue_requests(answer=true)
       @options[:queue_requests] = answer
     end
@@ -530,7 +694,7 @@
     #                          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
+    #                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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/events.rb new/lib/puma/events.rb
--- old/lib/puma/events.rb      2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/events.rb      2019-08-08 21:28:03.000000000 +0200
@@ -29,8 +29,8 @@
     #
     def initialize(stdout, stderr)
       @formatter = DefaultFormatter.new
-      @stdout = stdout
-      @stderr = stderr
+      @stdout = stdout.dup
+      @stderr = stderr.dup
 
       @stdout.sync = true
       @stderr.sync = true
@@ -93,7 +93,10 @@
     # parsing exception.
     #
     def parse_error(server, env, error)
-      @stderr.puts "#{Time.now}: HTTP parse error, malformed request 
(#{env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR]}): #{error.inspect}\n---\n"
+      @stderr.puts "#{Time.now}: HTTP parse error, malformed request " \
+        "(#{env[HTTP_X_FORWARDED_FOR] || 
env[REMOTE_ADDR]}#{env[REQUEST_PATH]}): " \
+        "#{error.inspect}" \
+        "\n---\n"
     end
 
     # An SSL error has occurred.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/launcher.rb new/lib/puma/launcher.rb
--- old/lib/puma/launcher.rb    2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/launcher.rb    2019-08-08 21:28:03.000000000 +0200
@@ -63,6 +63,9 @@
       @options = @config.options
       @config.clamp
 
+      @events.formatter = Events::PidFormatter.new if clustered?
+      @events.formatter = options[:log_formatter] if @options[:log_formatter]
+
       generate_restart_data
 
       if clustered? && !Process.respond_to?(:fork)
@@ -81,7 +84,6 @@
       set_rack_environment
 
       if clustered?
-        @events.formatter = Events::PidFormatter.new
         @options[:logger] = @events
 
         @runner = Cluster.new(self, @events)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/minissl.rb new/lib/puma/minissl.rb
--- old/lib/puma/minissl.rb     2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/minissl.rb     2019-08-08 21:28:03.000000000 +0200
@@ -54,22 +54,21 @@
           output = engine_read_all
           return output if output
 
-          begin
-            data = @socket.read_nonblock(size, exception: false)
-            if data == :wait_readable || data == :wait_writable
-              if @socket.to_io.respond_to?(data)
-                @socket.to_io.__send__(data)
-              elsif data == :wait_readable
-                IO.select([@socket.to_io])
-              else
-                IO.select(nil, [@socket.to_io])
-              end
-            elsif !data
-              return nil
-            else
-              break
-            end
-          end while true
+          data = @socket.read_nonblock(size, exception: false)
+          if data == :wait_readable || data == :wait_writable
+            # It would make more sense to let @socket.read_nonblock raise
+            # EAGAIN if necessary but it seems like it'll misbehave on Windows.
+            # I don't have a Windows machine to debug this so I can't explain
+            # exactly whats happening in that OS. Please let me know if you
+            # find out!
+            #
+            # In the meantime, we can emulate the correct behavior by
+            # capturing :wait_readable & :wait_writable and raising EAGAIN
+            # ourselves.
+            raise IO::EAGAINWaitReadable
+          elsif data.nil?
+            return nil
+          end
 
           @engine.inject(data)
           output = engine_read_all
@@ -177,10 +176,11 @@
 
     class Context
       attr_accessor :verify_mode
-      attr_reader :no_tlsv1
+      attr_reader :no_tlsv1, :no_tlsv1_1
 
       def initialize
-        @no_tlsv1 = false
+        @no_tlsv1   = false
+        @no_tlsv1_1 = false
       end
 
       if defined?(JRUBY_VERSION)
@@ -220,18 +220,24 @@
           @ca = ca
         end
 
-
         def check
           raise "Key not configured" unless @key
           raise "Cert not configured" unless @cert
         end
       end
 
+      # disables TLSv1
       def no_tlsv1=(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)
+        @no_tlsv1_1 = tlsv1_1
+      end
+
     end
 
     VERIFY_NONE = 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/plugin/tmp_restart.rb 
new/lib/puma/plugin/tmp_restart.rb
--- old/lib/puma/plugin/tmp_restart.rb  2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/plugin/tmp_restart.rb  2019-08-08 21:28:03.000000000 +0200
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 require 'puma/plugin'
 
 Puma::Plugin.create do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/rack/builder.rb new/lib/puma/rack/builder.rb
--- old/lib/puma/rack/builder.rb        2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/rack/builder.rb        2019-08-08 21:28:03.000000000 +0200
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 module Puma
 end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/rack/urlmap.rb new/lib/puma/rack/urlmap.rb
--- old/lib/puma/rack/urlmap.rb 2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/rack/urlmap.rb 2019-08-08 21:28:03.000000000 +0200
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 module Puma::Rack
   # Rack::URLMap takes a hash mapping urls or paths to apps, and
   # dispatches accordingly.  Support for HTTP/1.1 host names exists if
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/rack_default.rb new/lib/puma/rack_default.rb
--- old/lib/puma/rack_default.rb        2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/rack_default.rb        2019-08-08 21:28:03.000000000 +0200
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 require 'rack/handler/puma'
 
 module Rack::Handler
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/reactor.rb new/lib/puma/reactor.rb
--- old/lib/puma/reactor.rb     2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/reactor.rb     2019-08-08 21:28:03.000000000 +0200
@@ -23,7 +23,7 @@
   # A connection comes into a `Puma::Server` instance, it is then passed to a 
`Puma::Reactor` instance,
   # which stores it in an array and waits for any of the connections to be 
ready for reading.
   #
-  # The waiting/wake up is performed with nio4r, which will use the apropriate 
backend (libev, Java NIO or
+  # The waiting/wake up is performed with nio4r, which will use the 
appropriate backend (libev, Java NIO or
   # just plain IO#select). The call to `NIO::Selector#select` will "wake up" 
and
   # return the references to any objects that caused it to "wake". The reactor
   # then loops through each of these request objects, and sees if they're 
complete. If they
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/runner.rb new/lib/puma/runner.rb
--- old/lib/puma/runner.rb      2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/runner.rb      2019-08-08 21:28:03.000000000 +0200
@@ -14,6 +14,7 @@
       @options = cli.options
       @app = nil
       @control = nil
+      @started_at = Time.now
     end
 
     def daemon?
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/server.rb new/lib/puma/server.rb
--- old/lib/puma/server.rb      2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/server.rb      2019-08-08 21:28:03.000000000 +0200
@@ -588,8 +588,11 @@
     end
 
     def default_server_port(env)
-      return PORT_443 if env[HTTPS_KEY] == 'on' || env[HTTPS_KEY] == 'https'
-      env['HTTP_X_FORWARDED_PROTO'] == 'https' ? PORT_443 : PORT_80
+      if ['on', HTTPS].include?(env[HTTPS_KEY]) || 
env[HTTP_X_FORWARDED_PROTO].to_s[0...5] == HTTPS || 
env[HTTP_X_FORWARDED_SCHEME] == HTTPS || env[HTTP_X_FORWARDED_SSL] == "on"
+        PORT_443
+      else
+        PORT_80
+      end
     end
 
     # Takes the request +req+, invokes the Rack application to construct
@@ -627,23 +630,27 @@
       head = env[REQUEST_METHOD] == HEAD
 
       env[RACK_INPUT] = body
-      env[RACK_URL_SCHEME] =  env[HTTPS_KEY] ? HTTPS : HTTP
+      env[RACK_URL_SCHEME] = default_server_port(env) == PORT_443 ? HTTPS : 
HTTP
 
       if @early_hints
         env[EARLY_HINTS] = lambda { |headers|
-          fast_write client, "HTTP/1.1 103 Early Hints\r\n".freeze
+          begin
+            fast_write client, "HTTP/1.1 103 Early Hints\r\n".freeze
 
-          headers.each_pair do |k, vs|
-            if vs.respond_to?(:to_s) && !vs.to_s.empty?
-              vs.to_s.split(NEWLINE).each do |v|
-                fast_write client, "#{k}: #{v}\r\n"
+            headers.each_pair do |k, vs|
+              if vs.respond_to?(:to_s) && !vs.to_s.empty?
+                vs.to_s.split(NEWLINE).each do |v|
+                  fast_write client, "#{k}: #{v}\r\n"
+                end
+              else
+                fast_write client, "#{k}: #{vs}\r\n"
               end
-            else
-              fast_write client, "#{k}: #{vs}\r\n"
             end
-          end
 
-          fast_write client, "\r\n".freeze
+            fast_write client, "\r\n".freeze
+          rescue ConnectionError
+            # noop, if we lost the socket we just won't send the early hints
+          end
         }
       end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/single.rb new/lib/puma/single.rb
--- old/lib/puma/single.rb      2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma/single.rb      2019-08-08 21:28:03.000000000 +0200
@@ -18,7 +18,7 @@
       r = @server.running || 0
       t = @server.pool_capacity || 0
       m = @server.max_threads || 0
-      %Q!{ "backlog": #{b}, "running": #{r}, "pool_capacity": #{t}, 
"max_threads": #{m} }!
+      %Q!{ "started_at": "#{@started_at.utc.iso8601}", "backlog": #{b}, 
"running": #{r}, "pool_capacity": #{t}, "max_threads": #{m} }!
     end
 
     def restart
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma.rb new/lib/puma.rb
--- old/lib/puma.rb     2019-07-11 19:49:53.000000000 +0200
+++ new/lib/puma.rb     2019-08-08 21:28:03.000000000 +0200
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 # Standard libraries
 require 'socket'
 require 'tempfile'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/handler/puma.rb new/lib/rack/handler/puma.rb
--- old/lib/rack/handler/puma.rb        2019-07-11 19:49:53.000000000 +0200
+++ new/lib/rack/handler/puma.rb        2019-08-08 21:28:03.000000000 +0200
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 require 'rack/handler'
 
 module Rack
@@ -86,7 +88,7 @@
           "Verbose"         => "Don't report each request (default: false)"
         }
       end
-    private
+
       def self.set_host_port_to_config(host, port, config)
         config.clear_binds! if host || port
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        2019-07-11 19:49:53.000000000 +0200
+++ new/metadata        2019-08-08 21:28:03.000000000 +0200
@@ -1,14 +1,14 @@
 --- !ruby/object:Gem::Specification
 name: puma
 version: !ruby/object:Gem::Version
-  version: 4.0.1
+  version: 4.1.0
 platform: ruby
 authors:
 - Evan Phoenix
 autorequire: 
 bindir: bin
 cert_chain: []
-date: 2019-07-11 00:00:00.000000000 Z
+date: 2019-08-08 00:00:00.000000000 Z
 dependencies:
 - !ruby/object:Gem::Dependency
   name: nio4r
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tools/jungle/init.d/puma new/tools/jungle/init.d/puma
--- old/tools/jungle/init.d/puma        2019-07-11 19:49:53.000000000 +0200
+++ new/tools/jungle/init.d/puma        2019-08-08 21:28:03.000000000 +0200
@@ -398,7 +398,7 @@
   ;;
   remove)
     if [ "$#" -lt 2 ]; then
-      echo "Please, specifiy the app's directory to remove."
+      echo "Please, specify the app's directory to remove."
       exit 1
     else
       do_remove $2


Reply via email to