Issue #493 resolved

connection not being closed properly

Anonymous created an issue

i'm not sure if this is cherrypy or python's httplib that has a problem, but here's the issue:

i have a small server like:



import cherrypy

class Root: @cherrypy.expose() def default(self,params,*kwargs): return "foo"

if name == "main": cherrypy.root = Root() cherrypy.config.update({'global' : {'server.socketPort' : 9090}}) cherrypy.server.start() }}}

i run that, then from a python prompt i do:


import httplib conn = httplib.HTTPConnection("localhost:9090") conn.request("POST", "/some/path")
response = conn.getresponse() }}}

and it hangs. the server log (on stdout) has:

{{{ 2006/03/17 12:04:26 HTTP INFO - POST /some/path HTTP/1.1 }}}

if i control-C the python session, i get:

{{{ Traceback (most recent call last): File "<stdin>", line 1, in ? File "/usr/lib/python2.4/", line 863, in getresponse response.begin() File "/usr/lib/python2.4/", line 333, in begin version, status, reason = self._read_status() File "/usr/lib/python2.4/", line 291, in _read_status line = self.fp.readline() File "/usr/lib/python2.4/", line 325, in readline data = recv(1) KeyboardInterrupt }}}

after that, when i close the python session, the server log adds the line:

{{{ - - [2006/03/17 12:10:07] "POST /some/path HTTP/1.1" 200 259 }}}

so it looks like the server is just never closing the socket. i don't get this hanging when making a similar request to an apache server, just cherrypy. i also don't get a hang when using, eg, curl to make the same POST request to the cherrypy server. it also doesn't hang if i make a GET request instead of POST (it does also hang on PUT or DELETE requests).

so like i said, i'm not sure this is cherrypy's issue or httplib's. it only seems to come up on a combination of both. but it is 100% reproducible and i haven't been able to come up with any workarounds so it's quite frustrating.

(this is with the 2.1.1 release (installed with easy_install))

Reported by

Comments (8)

  1. Anonymous

    just an addendum: the server also hangs. it won't handle any other requests. you can up the threadpool and the other threads will go on fine, but any thread that responds to the POST request from httplib will get stuck so you can eventually exhaust them all.

  2. Anonymous

    just verified that it still hangs using cherrypy's svn trunk. there is a slight difference in that the server doesn't print anything to the log at all until the interactive session is killed. but it still hangs both the server and the client.

  3. Anonymous

    i'm going to up the severity on this since it basically amounts to a trivial DoS against any cherrypy app that isn't behind apache/lighttpd.

  4. Robert Brewer

    Here's the deal: because the request body is None, httplib doesn't automatically include a "Content-Length" header in the request. But cgi.FieldStorage expects that a POST request will have a request body, so it waits forever for the client to stop sending the request body. That's just how sockets work--it's mostly your fault for submitting an ambiguous HTTP request ;), but partly httplib's fault for not protecting you from that by default, but partly CherryPy's fault for not protecting CP from that.

    This should be fixed in CP with the following changes:

    1. Add a timeout on the server's handler socket, changing the setblocking(1) call to:

        s, addr = self.socket.accept()
        if hasattr(s, 'settimeout'):

    The value of timeout_secs should probably be configurable. The only question is how long to wait by default. Apache [ uses a 300 second timer (not exactly the same as a timeout!)], but we can probably default to a much lower value for our timeout. 10 seconds?

    If the timeout expires, the server should respond with 400 or (better) 411. See

    2. Properly handle the "chunked" transfer-coding, and 3. At least respond to "chunked" with 501 Unimplemented until then.

    CP isn't HTTP/1.1 compliant until it handles chunked encoding. :(

  5. Log in to comment