Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package rubygem-puma for openSUSE:Factory 
checked in at 2022-02-14 22:36:09
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-puma (Old)
 and      /work/SRC/openSUSE:Factory/.rubygem-puma.new.1956 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-puma"

Mon Feb 14 22:36:09 2022 rev:49 rq:954164 version:5.6.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/rubygem-puma/rubygem-puma.changes        
2021-12-22 20:19:09.091877561 +0100
+++ /work/SRC/openSUSE:Factory/.rubygem-puma.new.1956/rubygem-puma.changes      
2022-02-14 22:37:05.153556713 +0100
@@ -1,0 +2,11 @@
+Sat Feb 12 16:18:43 UTC 2022 - Marcus Rueckert <mrueck...@suse.de>
+
+- Update to version 5.6.2
+  https://github.com/advisories/GHSA-rmj8-8hhh-gv5h
+  https://rubysec.com/advisories/CVE-2022-23634/
+
+  other changes:
+  https://github.com/puma/puma/releases/tag/v5.6.1
+  https://github.com/puma/puma/releases/tag/v5.6.0
+
+-------------------------------------------------------------------

Old:
----
  puma-5.5.2.gem

New:
----
  puma-5.6.2.gem

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

Other differences:
------------------
++++++ rubygem-puma.spec ++++++
--- /var/tmp/diff_new_pack.qINhO6/_old  2022-02-14 22:37:05.585557839 +0100
+++ /var/tmp/diff_new_pack.qINhO6/_new  2022-02-14 22:37:05.589557849 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package rubygem-puma
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -24,7 +24,7 @@
 #
 
 Name:           rubygem-puma
-Version:        5.5.2
+Version:        5.6.2
 Release:        0
 %define mod_name puma
 %define mod_full_name %{mod_name}-%{version}

++++++ puma-5.5.2.gem -> puma-5.6.2.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/History.md new/History.md
--- old/History.md      2021-10-13 01:07:08.000000000 +0200
+++ new/History.md      1980-01-01 01:00:00.000000000 +0100
@@ -1,3 +1,36 @@
+## 5.6.2 / 2022-02-11
+
+* Bugfix/Security
+  * Response body will always be `close`d. (GHSA-rmj8-8hhh-gv5h, related to 
[#2809])
+
+## 5.6.1 / 2022-01-26
+
+* Bugfixes
+  * Reverted a commit which appeared to be causing occasional blank header 
values ([#2809])
+
+## 5.6.0 / 2022-01-25
+
+* Features
+  * Support `localhost` integration in `ssl_bind` ([#2764], [#2708])
+  * Allow backlog parameter to be set with ssl_bind DSL ([#2780])
+  * Remove yaml (psych) requirement in StateFile ([#2784])
+  * Allow culling of oldest workers, previously was only youngest ([#2773], 
[#2794])
+  * Add worker_check_interval configuration option ([#2759])
+  * Always send lowlevel_error response to client ([#2731], [#2341])
+  * Support for cert_pem and key_pem with ssl_bind DSL ([#2728])
+
+* Bugfixes
+  * Keep thread names under 15 characters, prevents breakage on some OSes 
([#2733])
+  * Fix two 'old-style-definition' compile warning ([#2807], [#2806])
+  * Log environment correctly using option value ([#2799])
+  * Fix warning from Ruby master (will be 3.2.0) ([#2785])
+  * extconf.rb - fix openssl with old Windows builds ([#2757])
+  * server.rb - rescue handling (`Errno::EBADF`) for `@notify.close` ([#2745])
+
+* Refactor
+  * server.rb - refactor code using @options[:remote_address] ([#2742])
+  * [jruby] a couple refactorings - avoid copy-ing bytes ([#2730])
+
 ## 5.5.2 / 2021-10-12
 
 * Bugfixes
@@ -5,6 +38,9 @@
 
 ## 5.5.1 / 2021-10-12
 
+* Feature (added as mistake - we don't normally do this on bugfix releases, 
sorry!)
+  * Allow setting APP_ENV in preference to RACK_ENV or RAILS_ENV ([#2702])
+
 * Security
   * Do not allow LF as a line ending in a header (CVE-2021-41136)
 
@@ -261,6 +297,11 @@
   * Support parallel tests in verbose progress reporting ([#2223])
   * Refactor error handling in server accept loop ([#2239])
 
+## 4.3.10 / 2021-10-12
+
+* Bugfixes
+  * Allow UTF-8 in HTTP header values
+
 ## 4.3.9 / 2021-10-12
 
 * Security
@@ -1799,6 +1840,27 @@
 * Bugfixes
   * Your bugfix goes here <Most recent on the top, like GitHub> (#Github 
Number)
 
+[#2809]:https://github.com/puma/puma/pull/2809     "PR by @dentarg, merged 
2022-01-26"
+[#2764]:https://github.com/puma/puma/pull/2764     "PR by @dentarg, merged 
2022-01-18"
+[#2708]:https://github.com/puma/puma/issues/2708   "Issue by @erikaxel, closed 
2022-01-18"
+[#2780]:https://github.com/puma/puma/pull/2780     "PR by @dalibor, merged 
2022-01-01"
+[#2784]:https://github.com/puma/puma/pull/2784     "PR by @MSP-Greg, merged 
2022-01-01"
+[#2773]:https://github.com/puma/puma/pull/2773     "PR by @ob-stripe, merged 
2022-01-01"
+[#2794]:https://github.com/puma/puma/pull/2794     "PR by @johnnyshields, 
merged 2022-01-10"
+[#2759]:https://github.com/puma/puma/pull/2759     "PR by @ob-stripe, merged 
2021-12-11"
+[#2731]:https://github.com/puma/puma/pull/2731     "PR by @baelter, merged 
2021-11-02"
+[#2341]:https://github.com/puma/puma/issues/2341   "Issue by @cjlarose, closed 
2021-11-02"
+[#2728]:https://github.com/puma/puma/pull/2728     "PR by @dalibor, merged 
2021-10-31"
+[#2733]:https://github.com/puma/puma/pull/2733     "PR by @ob-stripe, merged 
2021-12-12"
+[#2807]:https://github.com/puma/puma/pull/2807     "PR by @MSP-Greg, merged 
2022-01-25"
+[#2806]:https://github.com/puma/puma/issues/2806   "Issue by @olleolleolle, 
closed 2022-01-25"
+[#2799]:https://github.com/puma/puma/pull/2799     "PR by @ags, merged 
2022-01-22"
+[#2785]:https://github.com/puma/puma/pull/2785     "PR by @MSP-Greg, merged 
2022-01-02"
+[#2757]:https://github.com/puma/puma/pull/2757     "PR by @MSP-Greg, merged 
2021-11-24"
+[#2745]:https://github.com/puma/puma/pull/2745     "PR by @MSP-Greg, merged 
2021-11-03"
+[#2742]:https://github.com/puma/puma/pull/2742     "PR by @MSP-Greg, merged 
2021-12-12"
+[#2730]:https://github.com/puma/puma/pull/2730     "PR by @kares, merged 
2021-11-01"
+[#2702]:https://github.com/puma/puma/pull/2702     "PR by @jacobherrington, 
merged 2021-09-21"
 [#2610]:https://github.com/puma/puma/pull/2610     "PR by @ye-lin-aung, merged 
2021-08-18"
 [#2257]:https://github.com/puma/puma/issues/2257   "Issue by @nateberkopec, 
closed 2021-08-18"
 [#2654]:https://github.com/puma/puma/pull/2654     "PR by @Roguelazer, merged 
2021-09-07"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/README.md new/README.md
--- old/README.md       2021-10-13 01:07:08.000000000 +0200
+++ new/README.md       1980-01-01 01:00:00.000000000 +0100
@@ -137,6 +137,11 @@
 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.
 
+Constants loaded by your application (such as `Rails`) will not be available 
in `on_worker_boot`.
+However, these constants _will_ be available if `preload_app!` is enabled, 
either explicitly in your `puma` config or automatically if
+using 2 or more workers in cluster mode.
+If `preload_app!` is not enabled and 1 worker is used, then `on_worker_boot` 
will fire, but your app will not be preloaded and constants will not be 
available.
+
 `before_fork` specifies a block to be run before workers are forked:
 
 ```ruby
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/docs/architecture.md new/docs/architecture.md
--- old/docs/architecture.md    2021-10-13 01:07:08.000000000 +0200
+++ new/docs/architecture.md    1980-01-01 01:00:00.000000000 +0100
@@ -31,10 +31,10 @@
 ![https://bit.ly/2zwzhEK](images/puma-connection-flow.png)
 
 * Upon startup, Puma listens on a TCP or UNIX socket.
-  * The backlog of this socket is configured (with a default of 1024). The
-    backlog determines the size of the queue for unaccepted connections.
-    Generally, you'll never hit the backlog cap in production. If the backlog 
is
-    full, the operating system refuses new connections.
+  * The backlog of this socket is configured with a default of 1024, but the
+    actual backlog value is capped by the `net.core.somaxconn` sysctl value.
+    The backlog determines the size of the queue for unaccepted connections. If
+    the backlog is full, the operating system is not accepting new connections.
   * This socket backlog is distinct from the `backlog` of work as reported by
     `Puma.stats` or the control server. The backlog that `Puma.stats` refers to
     represents the number of connections in the process' `todo` set waiting for
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/docs/signals.md new/docs/signals.md
--- old/docs/signals.md 2021-10-13 01:07:08.000000000 +0200
+++ new/docs/signals.md 1980-01-01 01:00:00.000000000 +0100
@@ -42,6 +42,7 @@
 - `INT ` equivalent of sending Ctrl-C to cluster. Puma will attempt to finish 
then exit.
 - `CHLD`
 - `URG ` refork workers in phases from worker 0 if `fork_workers` option is 
enabled.
+- `INFO` print backtraces of all puma threads
 
 ## Callbacks order in case of different signals
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ext/puma_http11/extconf.rb 
new/ext/puma_http11/extconf.rb
--- old/ext/puma_http11/extconf.rb      2021-10-13 01:07:08.000000000 +0200
+++ new/ext/puma_http11/extconf.rb      1980-01-01 01:00:00.000000000 +0100
@@ -11,7 +11,7 @@
 unless ENV["DISABLE_SSL"]
   dir_config("openssl")
 
-  found_ssl = if pkg_config 'openssl'
+  found_ssl = if (!$mingw || RUBY_VERSION >= '2.4') && (t = pkg_config 
'openssl')
     puts 'using OpenSSL pkgconfig (openssl.pc)'
     true
   elsif %w'crypto libeay32'.find {|crypto| have_library(crypto, 'BIO_read')} &&
@@ -33,11 +33,14 @@
     have_func  "SSL_CTX_set_min_proto_version(NULL, 0)", "openssl/ssl.h"
 
     have_func  "X509_STORE_up_ref"
-    have_func("SSL_CTX_set_ecdh_auto(NULL, 0)", "openssl/ssl.h")
+    have_func "SSL_CTX_set_ecdh_auto(NULL, 0)"         , "openssl/ssl.h"
+
+    # below are yes for 3.0.0 & later, use for OpenSSL 3 detection
+    have_func "SSL_get1_peer_certificate"              , "openssl/ssl.h"
 
     # Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated 
in 3.0
     if Random.respond_to?(:bytes)
-      $defs.push("-DHAVE_RANDOM_BYTES")
+      $defs.push "-DHAVE_RANDOM_BYTES"
       puts "checking for Random.bytes... yes"
     else
       puts "checking for Random.bytes... no"
@@ -48,11 +51,14 @@
 if ENV["MAKE_WARNINGS_INTO_ERRORS"]
   # Make all warnings into errors
   # Except `implicit-fallthrough` since most failures comes from ragel state 
machine generated code
-  if respond_to? :append_cflags
-    append_cflags config_string 'WERRORFLAG'
+  if respond_to?(:append_cflags, true) # Ruby 2.5 and later
+    append_cflags(config_string('WERRORFLAG') || '-Werror')
     append_cflags '-Wno-implicit-fallthrough'
   else
-    $CFLAGS += ' ' << (config_string 'WERRORFLAG') << ' 
-Wno-implicit-fallthrough'
+    # flag may not exist on some platforms, -Werror may not be defined on some 
platforms, but
+    # works with all in current CI
+    $CFLAGS << " #{config_string('WERRORFLAG') || '-Werror'}"
+    $CFLAGS << ' -Wno-implicit-fallthrough'
   end
 end
 
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      2021-10-13 01:07:08.000000000 +0200
+++ new/ext/puma_http11/mini_ssl.c      1980-01-01 01:00:00.000000000 +0100
@@ -49,7 +49,8 @@
     0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
 };
 
-DH *get_dh2048() {
+#ifndef HAVE_SSL_GET1_PEER_CERTIFICATE
+DH *get_dh2048(void) {
   /* `openssl dhparam -C 2048`
    * -----BEGIN DH PARAMETERS-----
    * MIIBCAKCAQEAjmh1uQHdTfxOyxEbKAV30fUfzqMDF/ChPzjfyzl2jcrqQMhrk76o
@@ -119,6 +120,7 @@
 
   return dh;
 }
+#endif
 
 static void
 sslctx_free(void *ptr) {
@@ -208,8 +210,13 @@
 #endif
   int ssl_options;
   VALUE key, cert, ca, verify_mode, ssl_cipher_filter, no_tlsv1, no_tlsv1_1,
-    verification_flags, session_id_bytes;
+    verification_flags, session_id_bytes, cert_pem, key_pem;
+#ifndef HAVE_SSL_GET1_PEER_CERTIFICATE
   DH *dh;
+#endif
+  BIO *bio;
+  X509 *x509;
+  EVP_PKEY *pkey;
 
 #if OPENSSL_VERSION_NUMBER < 0x10002000L
   EC_KEY *ecdh;
@@ -218,13 +225,15 @@
   TypedData_Get_Struct(self, SSL_CTX, &sslctx_type, ctx);
 
   key = rb_funcall(mini_ssl_ctx, rb_intern_const("key"), 0);
-  StringValue(key);
 
   cert = rb_funcall(mini_ssl_ctx, rb_intern_const("cert"), 0);
-  StringValue(cert);
 
   ca = rb_funcall(mini_ssl_ctx, rb_intern_const("ca"), 0);
 
+  cert_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("cert_pem"), 0);
+
+  key_pem = rb_funcall(mini_ssl_ctx, rb_intern_const("key_pem"), 0);
+
   verify_mode = rb_funcall(mini_ssl_ctx, rb_intern_const("verify_mode"), 0);
 
   ssl_cipher_filter = rb_funcall(mini_ssl_ctx, 
rb_intern_const("ssl_cipher_filter"), 0);
@@ -233,8 +242,31 @@
 
   no_tlsv1_1 = rb_funcall(mini_ssl_ctx, rb_intern_const("no_tlsv1_1"), 0);
 
-  SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
-  SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
+  if (!NIL_P(cert)) {
+    StringValue(cert);
+    SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
+  }
+
+  if (!NIL_P(key)) {
+    StringValue(key);
+    SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
+  }
+
+  if (!NIL_P(cert_pem)) {
+    bio = BIO_new(BIO_s_mem());
+    BIO_puts(bio, RSTRING_PTR(cert_pem));
+    x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+
+    SSL_CTX_use_certificate(ctx, x509);
+  }
+
+  if (!NIL_P(key_pem)) {
+    bio = BIO_new(BIO_s_mem());
+    BIO_puts(bio, RSTRING_PTR(key_pem));
+    pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
+
+    SSL_CTX_use_PrivateKey(ctx, pkey);
+  }
 
   verification_flags = rb_funcall(mini_ssl_ctx, 
rb_intern_const("verification_flags"), 0);
 
@@ -289,9 +321,6 @@
     SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");
   }
 
-  dh = get_dh2048();
-  SSL_CTX_set_tmp_dh(ctx, dh);
-
 #if OPENSSL_VERSION_NUMBER < 0x10002000L
   // Remove this case if OpenSSL 1.0.1 (now EOL) support is no
   // longer needed.
@@ -325,6 +354,15 @@
                                  SSL_MAX_SSL_SESSION_ID_LENGTH);
 
   // printf("\ninitialize end security_level %d\n", 
SSL_CTX_get_security_level(ctx));
+
+#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
+  // https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_dh_auto.html
+  SSL_CTX_set_dh_auto(ctx, 1);
+#else
+  dh = get_dh2048();
+  SSL_CTX_set_tmp_dh(ctx, dh);
+#endif
+
   rb_obj_freeze(self);
   return self;
 }
@@ -523,7 +561,11 @@
 
   TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
 
+#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
+  cert = SSL_get1_peer_certificate(conn->ssl);
+#else
   cert = SSL_get_peer_certificate(conn->ssl);
+#endif
   if(!cert) {
     /*
      * See if there was a failed certificate associated with this client.
@@ -580,7 +622,10 @@
   ERR_load_crypto_strings();
 
   mod = rb_define_module_under(puma, "MiniSSL");
+
   eng = rb_define_class_under(mod, "Engine", rb_cObject);
+  rb_undef_alloc_func(eng);
+
   sslctx = rb_define_class_under(mod, "SSLContext", rb_cObject);
   rb_define_alloc_func(sslctx, sslctx_alloc);
   rb_define_method(sslctx, "initialize", sslctx_initialize, 1);
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     2021-10-13 
01:07:08.000000000 +0200
+++ new/ext/puma_http11/org/jruby/puma/MiniSSL.java     1980-01-01 
01:00:00.000000000 +0100
@@ -6,6 +6,7 @@
 import org.jruby.RubyObject;
 import org.jruby.RubyString;
 import org.jruby.anno.JRubyMethod;
+import org.jruby.exceptions.RaiseException;
 import org.jruby.javasupport.JavaEmbedUtils;
 import org.jruby.runtime.Block;
 import org.jruby.runtime.ObjectAllocator;
@@ -80,11 +81,11 @@
     /**
      * Writes bytes to the buffer after ensuring there's room
      */
-    public void put(byte[] bytes) {
-      if (buffer.remaining() < bytes.length) {
-        resize(buffer.limit() + bytes.length);
+    private void put(byte[] bytes, final int offset, final int length) {
+      if (buffer.remaining() < length) {
+        resize(buffer.limit() + length);
       }
-      buffer.put(bytes);
+      buffer.put(bytes, offset, length);
     }
 
     /**
@@ -115,7 +116,7 @@
 
       buffer.get(bss);
       buffer.clear();
-      return new ByteList(bss);
+      return new ByteList(bss, false);
     }
 
     @Override
@@ -174,8 +175,6 @@
   @JRubyMethod
   public IRubyObject initialize(ThreadContext threadContext, IRubyObject 
miniSSLContext)
       throws KeyStoreException, NoSuchAlgorithmException, 
KeyManagementException {
-    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
-    KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType());
 
     String keystoreFile = miniSSLContext.callMethod(threadContext, 
"keystore").convertToString().asJavaString();
     KeyManagerFactory kmf = keyManagerFactoryMap.get(keystoreFile);
@@ -230,14 +229,9 @@
 
   @JRubyMethod
   public IRubyObject inject(IRubyObject arg) {
-    try {
-      byte[] bytes = arg.convertToString().getBytes();
-      inboundNetData.put(bytes);
-      return this;
-    } catch (Exception e) {
-      e.printStackTrace();
-      throw new RuntimeException(e);
-    }
+    ByteList bytes = arg.convertToString().getByteList();
+    inboundNetData.put(bytes.unsafeBytes(), bytes.getBegin(), 
bytes.getRealSize());
+    return this;
   }
 
   private enum SSLOperation {
@@ -297,7 +291,7 @@
   }
 
   @JRubyMethod
-  public IRubyObject read() throws Exception {
+  public IRubyObject read() {
     try {
       inboundNetData.flip();
 
@@ -342,55 +336,46 @@
         return getRuntime().getNil();
       }
 
-      RubyString str = getRuntime().newString("");
-      str.setValue(appDataByteList);
-      return str;
-    } catch (Exception e) {
-      throw getRuntime().newEOFError(e.getMessage());
+      return RubyString.newString(getRuntime(), appDataByteList);
+    } catch (SSLException e) {
+      RaiseException re = getRuntime().newEOFError(e.getMessage());
+      re.initCause(e);
+      throw re;
     }
   }
 
   @JRubyMethod
   public IRubyObject write(IRubyObject arg) {
-    try {
-      byte[] bls = arg.convertToString().getBytes();
-      outboundAppData = new MiniSSLBuffer(bls);
+    byte[] bls = arg.convertToString().getBytes();
+    outboundAppData = new MiniSSLBuffer(bls);
 
-      return getRuntime().newFixnum(bls.length);
-    } catch (Exception e) {
-      e.printStackTrace();
-      throw new RuntimeException(e);
-    }
+    return getRuntime().newFixnum(bls.length);
   }
 
   @JRubyMethod
-  public IRubyObject extract() throws SSLException {
+  public IRubyObject extract(ThreadContext context) {
     try {
       ByteList dataByteList = outboundNetData.asByteList();
       if (dataByteList != null) {
-        RubyString str = getRuntime().newString("");
-        str.setValue(dataByteList);
-        return str;
+        return RubyString.newString(context.runtime, dataByteList);
       }
 
       if (!outboundAppData.hasRemaining()) {
-        return getRuntime().getNil();
+        return context.nil;
       }
 
       outboundNetData.clear();
       doOp(SSLOperation.WRAP, outboundAppData, outboundNetData);
       dataByteList = outboundNetData.asByteList();
       if (dataByteList == null) {
-        return getRuntime().getNil();
+        return context.nil;
       }
 
-      RubyString str = getRuntime().newString("");
-      str.setValue(dataByteList);
-
-      return str;
-    } catch (Exception e) {
-      e.printStackTrace();
-      throw new RuntimeException(e);
+      return RubyString.newString(context.runtime, dataByteList);
+    } catch (SSLException e) {
+      RaiseException ex = context.runtime.newRuntimeError(e.toString());
+      ex.initCause(e);
+      throw ex;
     }
   }
 
@@ -398,7 +383,7 @@
   public IRubyObject peercert() throws CertificateEncodingException {
     try {
       return JavaEmbedUtils.javaToRuby(getRuntime(), 
engine.getSession().getPeerCertificates()[0].getEncoded());
-    } catch (SSLPeerUnverifiedException ex) {
+    } catch (SSLPeerUnverifiedException e) {
       return getRuntime().getNil();
     }
   }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ext/puma_http11/puma_http11.c 
new/ext/puma_http11/puma_http11.c
--- old/ext/puma_http11/puma_http11.c   2021-10-13 01:07:08.000000000 +0200
+++ new/ext/puma_http11/puma_http11.c   1980-01-01 01:00:00.000000000 +0100
@@ -451,7 +451,7 @@
 void Init_mini_ssl(VALUE mod);
 #endif
 
-void Init_puma_http11()
+void Init_puma_http11(void)
 {
 
   VALUE mPuma = rb_define_module("Puma");
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      2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/binder.rb      1980-01-01 01:00:00.000000000 +0100
@@ -30,6 +30,7 @@
 
     def initialize(events, conf = Configuration.new)
       @events = events
+      @conf = conf
       @listeners = []
       @inherited_fds = {}
       @activated_sockets = {}
@@ -167,9 +168,9 @@
             params = Util.parse_query uri.query
 
             opt = params.key?('low_latency') && params['low_latency'] != 
'false'
-            bak = params.fetch('backlog', 1024).to_i
+            backlog = params.fetch('backlog', 1024).to_i
 
-            io = add_tcp_listener uri.host, uri.port, opt, bak
+            io = add_tcp_listener uri.host, uri.port, opt, backlog
 
             @ios[ios_len..-1].each do |i|
               addr = loc_addr_str i
@@ -232,9 +233,21 @@
           # If key and certs are not defined and localhost gem is required.
           # localhost gem will be used for self signed
           # Load localhost authority if not loaded.
-          ctx = localhost_authority && localhost_authority_context if 
params.empty?
+          if params.values_at('cert', 'key').all? { |v| v.to_s.empty? }
+            ctx = localhost_authority && localhost_authority_context
+          end
 
-          ctx ||= MiniSSL::ContextBuilder.new(params, @events).context
+          ctx ||=
+            begin
+              # Extract cert_pem and key_pem from options[:store] if present
+              ['cert', 'key'].each do |v|
+                if params[v] && params[v].start_with?('store:')
+                  index = Integer(params.delete(v).split('store:').last)
+                  params["#{v}_pem"] = @conf.options[:store][index]
+                end
+              end
+              MiniSSL::ContextBuilder.new(params, @events).context
+            end
 
           if fd = @inherited_fds.delete(str)
             logger.log "* Inherited #{str}"
@@ -244,7 +257,8 @@
             logger.log "* Activated #{str}"
           else
             ios_len = @ios.length
-            io = add_ssl_listener uri.host, uri.port, ctx
+            backlog = params.fetch('backlog', 1024).to_i
+            io = add_ssl_listener uri.host, uri.port, ctx, 
optimize_for_latency = true, backlog
 
             @ios[ios_len..-1].each do |i|
               addr = loc_addr_str i
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/cli.rb new/lib/puma/cli.rb
--- old/lib/puma/cli.rb 2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/cli.rb 1980-01-01 01:00:00.000000000 +0100
@@ -11,16 +11,17 @@
 
 module Puma
   class << self
-    # The CLI exports its Puma::Configuration object here to allow
-    # apps to pick it up. An app needs to use it conditionally though
-    # since it is not set if the app is launched via another
-    # mechanism than the CLI class.
+    # The CLI exports a Puma::Configuration instance here to allow
+    # apps to pick it up. An app must load this object conditionally
+    # because it is not set if the app is launched via any mechanism
+    # other than the CLI class.
     attr_accessor :cli_config
   end
 
   # Handles invoke a Puma::Server in a command line style.
   #
   class CLI
+    # @deprecated 6.0.0
     KEYS_NOT_TO_PERSIST_IN_STATE = Launcher::KEYS_NOT_TO_PERSIST_IN_STATE
 
     # Create a new CLI object using +argv+ as the command line
@@ -184,6 +185,10 @@
             user_config.restart_command cmd
           end
 
+          o.on "-s", "--silent", "Do not log prompt messages other than 
errors" do
+            @events = Events.new NullIO.new, $stderr
+          end
+
           o.on "-S", "--state PATH", "Where to store the state details" do 
|arg|
             user_config.state_path arg
           end
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      2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/client.rb      1980-01-01 01:00:00.000000000 +0100
@@ -161,7 +161,7 @@
     def close
       begin
         @io.close
-      rescue IOError
+      rescue IOError, Errno::EBADF
         Puma::Util.purge_interrupt_queue
       end
     end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/cluster/worker.rb 
new/lib/puma/cluster/worker.rb
--- old/lib/puma/cluster/worker.rb      2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/cluster/worker.rb      1980-01-01 01:00:00.000000000 +0100
@@ -33,8 +33,8 @@
         Signal.trap "SIGINT", "IGNORE"
         Signal.trap "SIGCHLD", "DEFAULT"
 
-       Thread.new do
-          Puma.set_thread_name "worker check pipe"
+        Thread.new do
+          Puma.set_thread_name "wrkr check"
           @check_pipe.wait_readable
           log "! Detected parent died, dying"
           exit! 1
@@ -76,7 +76,7 @@
           end
 
           Thread.new do
-            Puma.set_thread_name "worker fork pipe"
+            Puma.set_thread_name "wrkr fork"
             while (idx = @fork_pipe.gets)
               idx = idx.to_i
               if idx == -1 # stop server
@@ -114,7 +114,7 @@
         while restart_server.pop
           server_thread = server.run
           stat_thread ||= Thread.new(@worker_write) do |io|
-            Puma.set_thread_name "stat payload"
+            Puma.set_thread_name "stat pld"
             base_payload = "p#{Process.pid}"
 
             while true
@@ -130,7 +130,7 @@
                 Puma::Util.purge_interrupt_queue
                 break
               end
-              sleep Const::WORKER_CHECK_INTERVAL
+              sleep @options[:worker_check_interval]
             end
           end
           server_thread.join
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/cluster/worker_handle.rb 
new/lib/puma/cluster/worker_handle.rb
--- old/lib/puma/cluster/worker_handle.rb       2021-10-13 01:07:08.000000000 
+0200
+++ new/lib/puma/cluster/worker_handle.rb       1980-01-01 01:00:00.000000000 
+0100
@@ -40,6 +40,10 @@
         @stage = :booted
       end
 
+      def term!
+        @term = true
+      end
+
       def term?
         @term
       end
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     2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/cluster.rb     1980-01-01 01:00:00.000000000 +0100
@@ -108,24 +108,42 @@
     def cull_workers
       diff = @workers.size - @options[:workers]
       return if diff < 1
+      debug "Culling #{diff} workers"
 
-      debug "Culling #{diff.inspect} workers"
+      workers = workers_to_cull(diff)
+      debug "Workers to cull: #{workers.inspect}"
 
-      workers_to_cull = @workers[-diff,diff]
-      debug "Workers to cull: #{workers_to_cull.inspect}"
-
-      workers_to_cull.each do |worker|
+      workers.each do |worker|
         log "- Worker #{worker.index} (PID: #{worker.pid}) terminating"
         worker.term
       end
     end
 
+    def workers_to_cull(diff)
+      workers = @workers.sort_by(&:started_at)
+
+      # In fork_worker mode, worker 0 acts as our master process.
+      # We should avoid culling it to preserve copy-on-write memory gains.
+      workers.reject! { |w| w.index == 0 } if @options[:fork_worker]
+
+      workers[cull_start_index(diff), diff]
+    end
+
+    def cull_start_index(diff)
+      case @options[:worker_culling_strategy]
+      when :oldest
+        0
+      else # :youngest
+        -diff
+      end
+    end
+
     # @!attribute [r] next_worker_index
     def next_worker_index
-      all_positions =  0...@options[:workers]
-      occupied_positions = @workers.map { |w| w.index }
-      available_positions = all_positions.to_a - occupied_positions
-      available_positions.first
+      occupied_positions = @workers.map(&:index)
+      idx = 0
+      idx += 1 until !occupied_positions.include?(idx)
+      idx
     end
 
     def all_workers_booted?
@@ -135,7 +153,7 @@
     def check_workers
       return if @next_check >= Time.now
 
-      @next_check = Time.now + Const::WORKER_CHECK_INTERVAL
+      @next_check = Time.now + @options[:worker_check_interval]
 
       timeout_workers
       wait_workers
@@ -440,7 +458,7 @@
                   workers_not_booted -= 1
                 when "e"
                   # external term, see worker method, Signal.trap "SIGTERM"
-                  w.instance_variable_set :@term, true
+                  w.term!
                 when "t"
                   w.term unless w.term?
                 when "p"
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       2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/configuration.rb       1980-01-01 01:00:00.000000000 +0100
@@ -11,6 +11,7 @@
 
     DefaultTCPHost = "0.0.0.0"
     DefaultTCPPort = 9292
+    DefaultWorkerCheckInterval = 5
     DefaultWorkerTimeout = 60
     DefaultWorkerShutdownTimeout = 30
   end
@@ -195,9 +196,11 @@
         :workers => Integer(ENV['WEB_CONCURRENCY'] || 0),
         :silence_single_worker_warning => false,
         :mode => :http,
+        :worker_check_interval => DefaultWorkerCheckInterval,
         :worker_timeout => DefaultWorkerTimeout,
         :worker_boot_timeout => DefaultWorkerTimeout,
         :worker_shutdown_timeout => DefaultWorkerShutdownTimeout,
+        :worker_culling_strategy => :youngest,
         :remote_address => :socket,
         :tag => method(:infer_tag),
         :environment => -> { ENV['APP_ENV'] || ENV['RACK_ENV'] || 
ENV['RAILS_ENV'] || 'development' },
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       2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/const.rb       1980-01-01 01:00:00.000000000 +0100
@@ -100,8 +100,8 @@
   # too taxing on performance.
   module Const
 
-    PUMA_VERSION = VERSION = "5.5.2".freeze
-    CODE_NAME = "Zawgyi".freeze
+    PUMA_VERSION = VERSION = "5.6.2".freeze
+    CODE_NAME = "Birdie's Version".freeze
 
     PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
 
@@ -235,9 +235,6 @@
 
     EARLY_HINTS = "rack.early_hints".freeze
 
-    # Minimum interval to checks worker health
-    WORKER_CHECK_INTERVAL = 5
-
     # Illegal character in the key or value of response header
     DQUOTE = "\"".freeze
     HTTP_HEADER_DELIMITER = Regexp.escape("(),/:;<=>?@[]{}\\").freeze
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/detect.rb new/lib/puma/detect.rb
--- old/lib/puma/detect.rb      2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/detect.rb      1980-01-01 01:00:00.000000000 +0100
@@ -10,8 +10,10 @@
 
   IS_JRUBY = Object.const_defined? :JRUBY_VERSION
 
-  IS_WINDOWS = !!(RUBY_PLATFORM =~ /mswin|ming|cygwin/ ||
-    IS_JRUBY && RUBY_DESCRIPTION =~ /mswin/)
+  IS_OSX = RUBY_PLATFORM.include? 'darwin'
+
+  IS_WINDOWS = !!(RUBY_PLATFORM =~ /mswin|ming|cygwin/) ||
+    IS_JRUBY && RUBY_DESCRIPTION.include?('mswin')
 
   # @version 5.2.0
   IS_MRI = (RUBY_ENGINE == 'ruby' || RUBY_ENGINE.nil?)
@@ -20,6 +22,10 @@
     IS_JRUBY
   end
 
+  def self.osx?
+    IS_OSX
+  end
+
   def self.windows?
     IS_WINDOWS
   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 2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/dsl.rb 1980-01-01 01:00:00.000000000 +0100
@@ -48,6 +48,8 @@
 
       ca_additions = "&ca=#{opts[:ca]}" if ['peer', 
'force_peer'].include?(verify)
 
+      backlog_str = opts[:backlog] ? "&backlog=#{Integer(opts[:backlog])}" : ''
+
       if defined?(JRUBY_VERSION)
         ssl_cipher_list = opts[:ssl_cipher_list] ?
           "&ssl_cipher_list=#{opts[:ssl_cipher_list]}" : nil
@@ -55,7 +57,7 @@
         keystore_additions = 
"keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
 
         "ssl://#{host}:#{port}?#{keystore_additions}#{ssl_cipher_list}" \
-          "&verify_mode=#{verify}#{tls_str}#{ca_additions}"
+          "&verify_mode=#{verify}#{tls_str}#{ca_additions}#{backlog_str}"
       else
         ssl_cipher_filter = opts[:ssl_cipher_filter] ?
           "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
@@ -64,7 +66,7 @@
           "&verification_flags=#{Array(ary).join ','}" : nil
 
         "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}" \
-          
"#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}"
+          
"#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}"
       end
     end
 
@@ -191,7 +193,7 @@
     end
 
     # Bind the server to +url+. "tcp://", "unix://" and "ssl://" are the only
-    # accepted protocols. Multiple urls can be bound to, calling `bind` does
+    # accepted protocols. Multiple urls can be bound to, calling +bind+ does
     # not overwrite previous bindings.
     #
     # The default is "tcp://0.0.0.0:9292".
@@ -436,8 +438,15 @@
       @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 this method.
+    # Instead of using +bind+ and manually constructing a URI like:
+    #
+    #    bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'
+    #
+    # you can use the this method.
+    #
+    # When binding on localhost you don't need to specify +cert+ and +key+,
+    # Puma will assume you are using the +localhost+ gem and try to load the
+    # appropriate files.
     #
     # @example
     #   ssl_bind '127.0.0.1', '9292', {
@@ -447,14 +456,25 @@
     #     verify_mode: verify_mode,         # default 'none'
     #     verification_flags: flags,        # optional, not supported by JRuby
     #   }
-    # @example For JRuby, two keys are required: keystore & keystore_pass.
+    #
+    # @example Using self-signed certificate with the +localhost+ gem:
+    #   ssl_bind '127.0.0.1', '9292'
+    #
+    # @example Alternatively, you can provide +cert_pem+ and +key_pem+:
+    #   ssl_bind '127.0.0.1', '9292', {
+    #     cert_pem: File.read(path_to_cert),
+    #     key_pem: File.read(path_to_key),
+    #   }
+    #
+    # @example For JRuby, two keys are required: +keystore+ & +keystore_pass+
     #   ssl_bind '127.0.0.1', '9292', {
     #     keystore: path_to_keystore,
     #     keystore_pass: password,
     #     ssl_cipher_list: cipher_list,     # optional
     #     verify_mode: verify_mode          # default 'none'
     #   }
-    def ssl_bind(host, port, opts)
+    def ssl_bind(host, port, opts = {})
+      add_pem_values_to_options_store(opts)
       bind self.class.ssl_bind_str(host, port, opts)
     end
 
@@ -727,6 +747,19 @@
       @options[:tag] = string.to_s
     end
 
+    # Change the default interval for checking workers.
+    #
+    # The default value is 5 seconds.
+    #
+    # @note Cluster mode only.
+    # @example
+    #   worker_check_interval 5
+    # @see Puma::Cluster#check_workers
+    #
+    def worker_check_interval(interval)
+      @options[:worker_check_interval] = Integer(interval)
+    end
+
     # 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.
@@ -741,7 +774,7 @@
     #
     def worker_timeout(timeout)
       timeout = Integer(timeout)
-      min = Const::WORKER_CHECK_INTERVAL
+      min = @options.fetch(:worker_check_interval, 
Puma::ConfigDefault::DefaultWorkerCheckInterval)
 
       if timeout <= min
         raise "The minimum worker_timeout must be greater than the worker 
reporting interval (#{min})"
@@ -773,6 +806,30 @@
       @options[:worker_shutdown_timeout] = Integer(timeout)
     end
 
+    # Set the strategy for worker culling.
+    #
+    # There are two possible values:
+    #
+    # 1. **:youngest** - the youngest workers (i.e. the workers that were
+    #    the most recently started) will be culled.
+    # 2. **:oldest** - the oldest workers (i.e. the workers that were started
+    #    the longest time ago) will be culled.
+    #
+    # @note Cluster mode only.
+    # @example
+    #   worker_culling_strategy :oldest
+    # @see Puma::Cluster#cull_workers
+    #
+    def worker_culling_strategy(strategy)
+      stategy = strategy.to_sym
+
+      if ![:youngest, :oldest].include?(strategy)
+        raise "Invalid value for worker_culling_strategy - #{stategy}"
+      end
+
+      @options[:worker_culling_strategy] = strategy
+    end
+
     # When set to true (the default), workers accept all requests
     # and queue them before passing them to the handlers.
     # When set to false, each worker process accepts exactly as
@@ -927,5 +984,25 @@
     def mutate_stdout_and_stderr_to_sync_on_write(enabled=true)
       @options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
     end
+
+    private
+
+    # To avoid adding cert_pem and key_pem as URI params, we store them on the
+    # options[:store] from where Puma binder knows how to find and extract 
them.
+    def add_pem_values_to_options_store(opts)
+      return if defined?(JRUBY_VERSION)
+
+      @options[:store] ||= []
+
+      # Store cert_pem and key_pem to options[:store] if present
+      [:cert, :key].each do |v|
+        opt_key = :"#{v}_pem"
+        if opts[opt_key]
+          index = @options[:store].length
+          @options[:store] << opts[opt_key]
+          opts[v] = "store:#{index}"
+        end
+      end
+    end
   end
 end
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    2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/launcher.rb    1980-01-01 01:00:00.000000000 +0100
@@ -15,6 +15,7 @@
   # It is responsible for either launching a cluster of Puma workers or a 
single
   # puma server.
   class Launcher
+    # @deprecated 6.0.0
     KEYS_NOT_TO_PERSIST_IN_STATE = [
        :logger, :lowlevel_error_handler,
        :before_worker_shutdown, :before_worker_boot, :before_worker_fork,
@@ -73,7 +74,7 @@
 
       generate_restart_data
 
-      if clustered? && !Process.respond_to?(:fork)
+      if clustered? && !Puma.forkable?
         unsupported "worker mode not supported on #{RUBY_ENGINE} on this 
platform"
       end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/minissl/context_builder.rb 
new/lib/puma/minissl/context_builder.rb
--- old/lib/puma/minissl/context_builder.rb     2021-10-13 01:07:08.000000000 
+0200
+++ new/lib/puma/minissl/context_builder.rb     1980-01-01 01:00:00.000000000 
+0100
@@ -23,17 +23,19 @@
           ctx.keystore_pass = params['keystore-pass']
           ctx.ssl_cipher_list = params['ssl_cipher_list'] if 
params['ssl_cipher_list']
         else
-          unless params['key']
-            events.error "Please specify the SSL key via 'key='"
+          if params['key'].nil? && params['key_pem'].nil?
+            events.error "Please specify the SSL key via 'key=' or 'key_pem='"
           end
 
-          ctx.key = params['key']
+          ctx.key = params['key'] if params['key']
+          ctx.key_pem = params['key_pem'] if params['key_pem']
 
-          unless params['cert']
-            events.error "Please specify the SSL cert via 'cert='"
+          if params['cert'].nil? && params['cert_pem'].nil?
+            events.error "Please specify the SSL cert via 'cert=' or 
'cert_pem='"
           end
 
-          ctx.cert = params['cert']
+          ctx.cert = params['cert'] if params['cert']
+          ctx.cert_pem = params['cert_pem'] if params['cert_pem']
 
           if ['peer', 'force_peer'].include?(params['verify_mode'])
             unless params['ca']
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     2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/minissl.rb     1980-01-01 01:00:00.000000000 +0100
@@ -208,6 +208,10 @@
       def initialize
         @no_tlsv1   = false
         @no_tlsv1_1 = false
+        @key = nil
+        @cert = nil
+        @key_pem = nil
+        @cert_pem = nil
       end
 
       if IS_JRUBY
@@ -230,6 +234,8 @@
         attr_reader :key
         attr_reader :cert
         attr_reader :ca
+        attr_reader :cert_pem
+        attr_reader :key_pem
         attr_accessor :ssl_cipher_filter
         attr_accessor :verification_flags
 
@@ -248,9 +254,19 @@
           @ca = ca
         end
 
+        def cert_pem=(cert_pem)
+          raise ArgumentError, "'cert_pem' is not a String" unless 
cert_pem.is_a? String
+          @cert_pem = cert_pem
+        end
+
+        def key_pem=(key_pem)
+          raise ArgumentError, "'key_pem' is not a String" unless 
key_pem.is_a? String
+          @key_pem = key_pem
+        end
+
         def check
-          raise "Key not configured" unless @key
-          raise "Cert not configured" unless @cert
+          raise "Key not configured" if @key.nil? && @key_pem.nil?
+          raise "Cert not configured" if @cert.nil? && @cert_pem.nil?
         end
       end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/plugin.rb new/lib/puma/plugin.rb
--- old/lib/puma/plugin.rb      2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/plugin.rb      1980-01-01 01:00:00.000000000 +0100
@@ -64,7 +64,7 @@
     def fire_background
       @background.each_with_index do |b, i|
         Thread.new do
-          Puma.set_thread_name "plugin background #{i}"
+          Puma.set_thread_name "plgn bg #{i}"
           b.call
         end
       end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/request.rb new/lib/puma/request.rb
--- old/lib/puma/request.rb     2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/request.rb     1980-01-01 01:00:00.000000000 +0100
@@ -167,11 +167,16 @@
         end
 
       ensure
-        uncork_socket io
+        begin
+          uncork_socket io
 
-        body.close
-        client.tempfile.unlink if client.tempfile
-        res_body.close if res_body.respond_to? :close
+          body.close
+          client.tempfile.unlink if client.tempfile
+        ensure
+          # Whatever happens, we MUST call `close` on the response body.
+          # Otherwise Rack::BodyProxy callbacks may not fire and lead to 
various state leaks
+          res_body.close if res_body.respond_to? :close
+        end
 
         after_reply.each { |o| o.call }
       end
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      2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/runner.rb      1980-01-01 01:00:00.000000000 +0100
@@ -69,7 +69,7 @@
 
       control.binder.parse [str], self, 'Starting control server'
 
-      control.run thread_name: 'control'
+      control.run thread_name: 'ctl'
       @control = control
     end
 
@@ -94,12 +94,13 @@
     def output_header(mode)
       min_t = @options[:min_threads]
       max_t = @options[:max_threads]
+      environment = @options[:environment]
 
       log "Puma starting in #{mode} mode..."
       log "* Puma version: #{Puma::Const::PUMA_VERSION} (#{ruby_engine}) 
(\"#{Puma::Const::CODE_NAME}\")"
       log "*  Min threads: #{min_t}"
       log "*  Max threads: #{max_t}"
-      log "*  Environment: #{ENV['RACK_ENV']}"
+      log "*  Environment: #{environment}"
 
       if mode == "cluster"
         log "*   Master PID: #{Process.pid}"
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      2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/server.rb      1980-01-01 01:00:00.000000000 +0100
@@ -220,7 +220,7 @@
     # up in the background to handle requests. Otherwise requests
     # are handled synchronously.
     #
-    def run(background=true, thread_name: 'server')
+    def run(background=true, thread_name: 'srv')
       BasicSocket.do_not_reverse_lookup = true
 
       @events.fire :state, :booting
@@ -315,16 +315,15 @@
         queue_requests = @queue_requests
         drain = @options[:drain_on_shutdown] ? 0 : nil
 
-        remote_addr_value = nil
-        remote_addr_header = nil
-
-        case @options[:remote_address]
+        addr_send_name, addr_value = case @options[:remote_address]
         when :value
-          remote_addr_value = @options[:remote_address_value]
+          [:peerip=, @options[:remote_address_value]]
         when :header
-          remote_addr_header = @options[:remote_address_header]
+          [:remote_addr_header=, @options[:remote_address_header]]
         when :proxy_protocol
-          remote_addr_proxy_protocol = @options[:remote_address_proxy_protocol]
+          [:expect_proxy_proto=, @options[:remote_address_proxy_protocol]]
+        else
+          [nil, nil]
         end
 
         while @status == :run || (drain && shutting_down?)
@@ -344,16 +343,10 @@
                   next
                 end
                 drain += 1 if shutting_down?
-                client = Client.new io, @binder.env(sock)
-                client.listener = sock
-                if remote_addr_value
-                  client.peerip = remote_addr_value
-                elsif remote_addr_header
-                  client.remote_addr_header = remote_addr_header
-                elsif remote_addr_proxy_protocol
-                  client.expect_proxy_proto = remote_addr_proxy_protocol
-                end
-                pool << client
+                pool << Client.new(io, @binder.env(sock)).tap { |c|
+                  c.listener = sock
+                  c.send(addr_send_name, addr_value) if addr_value
+                }
               end
             end
           rescue IOError, Errno::EBADF
@@ -375,13 +368,14 @@
       rescue Exception => e
         @events.unknown_error e, nil, "Exception handling servers"
       ensure
-        begin
-          @check.close unless @check.closed?
-        rescue Errno::EBADF, RuntimeError
-          # RuntimeError is Ruby 2.2 issue, can't modify frozen IOError
-          # Errno::EBADF is infrequently raised
+        # RuntimeError is Ruby 2.2 issue, can't modify frozen IOError
+        # Errno::EBADF is infrequently raised
+        [@check, @notify].each do |io|
+          begin
+            io.close unless io.closed?
+          rescue Errno::EBADF, RuntimeError
+          end
         end
-        @notify.close
         @notify = nil
         @check = nil
       end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/state_file.rb new/lib/puma/state_file.rb
--- old/lib/puma/state_file.rb  2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/state_file.rb  1980-01-01 01:00:00.000000000 +0100
@@ -1,15 +1,40 @@
 # frozen_string_literal: true
 
-require 'yaml'
-
 module Puma
+
+  # Puma::Launcher uses StateFile to write a yaml file for use with 
Puma::ControlCLI.
+  #
+  # In previous versions of Puma, YAML was used to read/write the state file.
+  # Since Puma is similar to Bundler/RubyGems in that it may load before one's 
app
+  # does, minimizing the dependencies that may be shared with the app is 
desired.
+  #
+  # At present, it only works with numeric and string values.  It is still a 
valid
+  # yaml file, and the CI tests parse it with Psych.
+  #
   class StateFile
+
+    ALLOWED_FIELDS = %w!control_url control_auth_token pid running_from!
+
+    # @deprecated 6.0.0
+    FIELDS = ALLOWED_FIELDS
+
     def initialize
       @options = {}
     end
 
     def save(path, permission = nil)
-      contents =YAML.dump @options
+      contents = "---\n".dup
+      @options.each do |k,v|
+        next unless ALLOWED_FIELDS.include? k
+        case v
+        when Numeric
+          contents << "#{k}: #{v}\n"
+        when String
+          next if v.strip.empty?
+          contents << (k == 'running_from' || v.to_s.include?(' ') ?
+            "#{k}: \"#{v}\"\n" : "#{k}: #{v}\n")
+        end
+      end
       if permission
         File.write path, contents, mode: 'wb:UTF-8'
       else
@@ -18,12 +43,21 @@
     end
 
     def load(path)
-      @options = YAML.load File.read(path)
+      File.read(path).lines.each do |line|
+        next if line.start_with? '#'
+        k,v = line.split ':', 2
+        next unless v && ALLOWED_FIELDS.include?(k)
+        v = v.strip
+        @options[k] =
+          case v
+          when /\A\d+\z/       then v.to_i
+          when /\A\d+\.\d+\z/  then v.to_f
+          else                      v.gsub(/\A"|"\z/, '')
+          end
+      end
     end
 
-    FIELDS = %w!control_url control_auth_token pid running_from!
-
-    FIELDS.each do |f|
+    ALLOWED_FIELDS.each do |f|
       define_method f do
         @options[f]
       end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/puma/thread_pool.rb new/lib/puma/thread_pool.rb
--- old/lib/puma/thread_pool.rb 2021-10-13 01:07:08.000000000 +0200
+++ new/lib/puma/thread_pool.rb 1980-01-01 01:00:00.000000000 +0100
@@ -72,7 +72,7 @@
     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
+      Thread.current.keys.each do |key| # rubocop: disable 
Style/HashEachMethods
         Thread.current[key] = nil unless key == :__recursive_key__
       end
     end
@@ -102,7 +102,7 @@
       @spawned += 1
 
       th = Thread.new(@spawned) do |spawned|
-        Puma.set_thread_name '%s threadpool %03i' % [@name, spawned]
+        Puma.set_thread_name '%s tp %03i' % [@name, spawned]
         todo  = @todo
         block = @block
         mutex = @mutex
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        2021-10-13 01:07:08.000000000 +0200
+++ new/metadata        1980-01-01 01:00:00.000000000 +0100
@@ -1,14 +1,14 @@
 --- !ruby/object:Gem::Specification
 name: puma
 version: !ruby/object:Gem::Version
-  version: 5.5.2
+  version: 5.6.2
 platform: ruby
 authors:
 - Evan Phoenix
 autorequire:
 bindir: bin
 cert_chain: []
-date: 2021-10-12 00:00:00.000000000 Z
+date: 1980-01-01 00:00:00.000000000 Z
 dependencies:
 - !ruby/object:Gem::Dependency
   name: nio4r
@@ -140,7 +140,7 @@
     - !ruby/object:Gem::Version
       version: '0'
 requirements: []
-rubygems_version: 3.2.3
+rubygems_version: 3.2.26
 signing_key:
 specification_version: 4
 summary: Puma is a simple, fast, threaded, and highly parallel HTTP 1.1 server 
for
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tools/Dockerfile new/tools/Dockerfile
--- old/tools/Dockerfile        2021-10-13 01:07:08.000000000 +0200
+++ new/tools/Dockerfile        1980-01-01 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
 # Use this Dockerfile to create minimal reproductions of issues
 
-FROM ruby:2.6
+FROM ruby:3.1
 
 # throw errors if Gemfile has been modified since Gemfile.lock
 RUN bundle config --global frozen 1

Reply via email to