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

More gracefully deal with SSL sessions. Fixes #1002

The problem was a few points:

* We were not clearing the reactor on a normal stop, which is what
  is used in a phased restart.
* On close, SSL sockets were not sending the shutdown message.
* SSL sockets that were completely uninitialized ended up sitting
  in reactor and could not actually be shutdown because there were
  not initialized.
This commit is contained in:
Evan Phoenix 2016-07-25 17:20:17 -07:00
parent 2f7364f170
commit 46416cb49e
4 changed files with 66 additions and 2 deletions

View file

@ -3,6 +3,8 @@ require 'mkmf'
dir_config("puma_http11")
unless ENV["DISABLE_SSL"]
dir_config("openssl")
if %w'crypto libeay32'.find {|crypto| have_library(crypto, 'BIO_read')} and
%w'ssl ssleay32'.find {|ssl| have_library(ssl, 'SSL_CTX_new')}

View file

@ -327,6 +327,33 @@ VALUE engine_extract(VALUE self) {
return Qnil;
}
VALUE engine_shutdown(VALUE self) {
ms_conn* conn;
int ok, err;
char buf[512];
Data_Get_Struct(self, ms_conn, conn);
ERR_clear_error();
ok = SSL_shutdown(conn->ssl);
if (ok == 0) {
return Qfalse;
}
return Qtrue;
}
VALUE engine_init(VALUE self) {
ms_conn* conn;
int ok, err;
char buf[512];
Data_Get_Struct(self, ms_conn, conn);
return SSL_in_init(conn->ssl) ? Qtrue : Qfalse;
}
VALUE engine_peercert(VALUE self) {
ms_conn* conn;
X509* cert;
@ -394,6 +421,10 @@ void Init_mini_ssl(VALUE puma) {
rb_define_method(eng, "write", engine_write, 1);
rb_define_method(eng, "extract", engine_extract, 0);
rb_define_method(eng, "shutdown", engine_shutdown, 0);
rb_define_method(eng, "init?", engine_init, 0);
rb_define_method(eng, "peercert", engine_peercert, 0);
}

View file

@ -81,7 +81,38 @@ module Puma
end
def close
@socket.close
begin
# Try to setup (so that we can then close them) any
# partially initialized sockets.
while @engine.init?
# Don't let this socket hold this loop forever.
# If it can't send more packets within 1s, then
# give up.
return unless IO.select([@socket], nil, nil, 1)
begin
read_nonblock(1024)
rescue Errno::EAGAIN
end
end
done = @engine.shutdown
while true
enc = @engine.extract
@socket.write enc
notify = @socket.sysread(1024)
@engine.inject notify
done = @engine.shutdown
break if done
end
rescue IOError, SystemCallError
# nothing
ensure
@socket.close
end
end
def peeraddr

View file

@ -358,7 +358,7 @@ module Puma
graceful_shutdown if @status == :stop || @status == :restart
if queue_requests
@reactor.clear! if @status == :restart
@reactor.clear!
@reactor.shutdown
end
rescue Exception => e