I have a production WEBrick server whose common usage includes clients 
making requests and then disconnecting before a response can be given. 
There is a bug in WEBrick::GenericServer#start_thread that can cause 
threads to silently die under these conditions, causing the thread pool 
to eventually be exhausted, triggering the error reported in 
ruby-talk:86309. Basically, the call to sock.peeraddr can result in an 
exception being raised, which causes the addr local variable to be nil 
when the ensure block is executed, raising an additional exception 
which is not handled.

The patch below should fix that bug. I've also included some improved 
error-handling which rescues all Exceptions (not just StandardError), 
and keeps the server a bit quieter under normal operation.

Let me know if you have any questions or need more info about the patch.

Thanks,


Nathaniel

<:((><


Index: lib/webrick/httpresponse.rb
===================================================================
RCS file: /src/ruby/lib/webrick/httpresponse.rb,v
retrieving revision 1.2
diff -u -r1.2 httpresponse.rb
--- lib/webrick/httpresponse.rb	25 Nov 2003 16:02:45 -0000	1.2
+++ lib/webrick/httpresponse.rb	1 Dec 2003 20:25:26 -0000
@@ -84,10 +84,10 @@
          setup_header()
          send_header(socket)
          send_body(socket)
-      rescue Errno::EPIPE
-        @logger.error("HTTPResponse#send_response: EPIPE occured.")
+      rescue Errno::EPIPE, Errno::ECONNRESET, Errno::ENOTCONN => ex
+        @logger.debug(ex)
          @keep_alive = false
-      rescue => ex
+      rescue Exception => ex
          @logger.error(ex)
          @keep_alive = false
        end
Index: lib/webrick/server.rb
===================================================================
RCS file: /src/ruby/lib/webrick/server.rb,v
retrieving revision 1.4
diff -u -r1.4 server.rb
--- lib/webrick/server.rb	23 Oct 2003 11:29:29 -0000	1.4
+++ lib/webrick/server.rb	1 Dec 2003 20:25:26 -0000
@@ -102,7 +102,7 @@
            rescue Errno::EBADF, IOError => ex
              # if the listening socket was closed in 
GenericServer#shutdown,
              # IO::select raise it.
-          rescue => ex
+          rescue Exception => ex
              msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
              @logger.error msg
            end
@@ -148,14 +148,20 @@
            @logger.debug "accept: #{addr[3]}:#{addr[1]}"
            call_callback(:AcceptCallback, sock)
            block ? block.call(sock) : run(sock)
-        rescue ServerError, Errno::ENOTCONN => ex
+        rescue Errno::ENOTCONN
+          @logger.debug "Errno::ENOTCONN raised"
+        rescue ServerError => ex
            msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
            @logger.error msg
          rescue Exception => ex
            @logger.error ex
          ensure
            Thread.current[:WEBrickSocket] = nil
-          @logger.debug "close: #{addr[3]}:#{addr[1]}"
+          if(addr)
+            @logger.debug "close: #{addr[3]}:#{addr[1]}"
+          else
+            @logger.debug "close: nil"
+          end
            sock.close
          end
          @tokens.push(nil)