From 6f226d9d42676860cdabc1e1c85cb9e9202e8ddd Mon Sep 17 00:00:00 2001 From: akr Date: Fri, 30 May 2014 12:32:48 +0000 Subject: * lib/webrick/server.rb: Use a pipe to detect server shutdown. shutdown() or close() for listening socket is not a reliable. Actually, both doesn't work (doesn't wake up select()) on DragonFly BSD 3.6.2. * test/webrick/utils.rb: :ShutdownSocketWithoutClose is not required now to immediate server shutdown detection. This fixes fd leaks. * test/net/http/utils.rb: Ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46253 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- lib/webrick/server.rb | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/webrick/server.rb b/lib/webrick/server.rb index bd8a045891..ca22f85ae9 100644 --- a/lib/webrick/server.rb +++ b/lib/webrick/server.rb @@ -115,6 +115,7 @@ module WEBrick @config[:Port] = @listeners[0].addr[1] end end + @shutdown_pipe_w = nil end ## @@ -157,6 +158,9 @@ module WEBrick raise ServerError, "already started." if @status != :Stop server_type = @config[:ServerType] || SimpleServer + shutdown_pipe_r, shutdown_pipe_w = IO.pipe + @shutdown_pipe_w = shutdown_pipe_w + server_type.start{ @logger.info \ "#{self.class}#start: pid=#{$$} port=#{@config[:Port]}" @@ -167,7 +171,10 @@ module WEBrick begin while @status == :Running begin - if svrs = IO.select(@listeners, nil, nil, 2.0) + if svrs = IO.select([shutdown_pipe_r, *@listeners], nil, nil, 2.0) + if svrs[0].include? shutdown_pipe_r + return + end svrs[0].each{|svr| @tokens.pop # blocks while no token is there. if sock = accept_client(svr) @@ -193,6 +200,14 @@ module WEBrick end ensure + shutdown_pipe_r.close + if !shutdown_pipe_w.closed? + begin + shutdown_pipe_w.close + rescue IOError # Another thread closed shutdown_pipe_w. + end + end + @shutdown_pipe_w = nil @status = :Shutdown @logger.info "going to shutdown ..." thgroup.list.each{|th| th.join if th[:WEBrickThread] } @@ -218,6 +233,16 @@ module WEBrick def shutdown stop + + shutdown_pipe_w = @shutdown_pipe_w + @shutdown_pipe_w = nil + if shutdown_pipe_w && !shutdown_pipe_w.closed? + begin + shutdown_pipe_w.close + rescue IOError # Another thread closed shutdown_pipe_w. + end + end + @listeners.each{|s| if @logger.debug? addr = s.addr -- cgit v1.2.3