Public bug reported:

When dealing with a new connection,
SocketServer.BaseRequestHandler.__init__ first calls the request handler
(self.handle below) and then calls cleanup code which closes the
connection (self.finish below).

class BaseRequestHandler:
    def __init__(self, request, client_address, server):
        < ... snip ... >
        try:
            self.handle()
        finally:
            self.finish()

The issue arises when a client disconnects suddenly during the
self.handle() call. The handler may attempt to write data to the
disconnected socket.  This will cause an exception (which is correct),
but somehow data will still be added to the connection's buffer and
self.wfile.closed will be False! As a result,
BaseRequestHandler.finish() will attempt to flush the connection's
buffer and this will raise another exception which can't be handled
without modifying the library code.

----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 62718)
Traceback (most recent call last):
  File "C:\Python27\lib\SocketServer.py", line 284, in _handle_request_noblock
    self.process_request(request, client_address)
  File "C:\Python27\lib\SocketServer.py", line 310, in process_request
    self.finish_request(request, client_address)
  File "C:\Python27\lib\SocketServer.py", line 323, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "C:\Python27\lib\SocketServer.py", line 641, in __init__
    self.finish()
  File "C:\Python27\lib\SocketServer.py", line 694, in finish
    self.wfile.flush()
  File "C:\Python27\lib\socket.py", line 303, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 10053] An established connection was aborted by the software in 
your host machine
----------------------------------------

I've provided a toy server below, you can reproduce the issue by
submitting a request to it with curl and then immediately killing curl:

 curl -d "test"  http://127.0.0.1:8000/

Toy server code:
===========================

import BaseHTTPServer
import SocketServer
import time

class ThreadedHTTPServer(BaseHTTPServer.HTTPServer):
  pass

class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
  def do_POST(self):
    try:
      length = int(self.headers["Content-Length"])
      request = self.rfile.read(length)

      print "Sleeping. Kill the 'curl' command now."
      time.sleep(10)
      print "Woke up. You should see a stack trace from the problematic 
exception below."

      print "Received POST: " + request
      self.send_response(200) # <------- This somehow adds to the connection's 
buffer!
      self.end_headers()
    except Exception as e:
      print "Exception: " + str(e)  # <----- This exception is expected

httpd = ThreadedHTTPServer(("127.0.0.1", 8000), RequestHandler)
httpd.serve_forever()
httpd.server_close()

** Affects: python
     Importance: Unknown
         Status: Unknown

** Affects: python2.7 (Ubuntu)
     Importance: Undecided
         Status: New


** Tags: precise quantal

** Bug watch added: Python Roundup #14574
   http://bugs.python.org/issue14574

** Also affects: python via
   http://bugs.python.org/issue14574
   Importance: Unknown
       Status: Unknown

** Tags added: precise quantal

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/1214848

Title:
  SocketServer doesn't handle client disconnects properly.

To manage notifications about this bug go to:
https://bugs.launchpad.net/python/+bug/1214848/+subscriptions

-- 
ubuntu-bugs mailing list
ubuntu-bugs@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to