SocketServer crash on my machine

xtian at xtian at
Fri Jun 29 08:11:03 CEST 2001

On 28 Jun 2001 00:42:06 GMT, gmcm at (Gordon McMillan)

>Syver Enstad wrote: 
>>I was checking out the the SocketServer example in Mark Lutz rather
>>excellent book Programming Python 2 edition,
>>    data = self.request.recv(1024)
>>  File "<string>", line 1, in recv
>>AttributeError: 'int' object has no attribute 'recv'
>The socket has already been closed.
>[more snippage]
>>class MyClientHandler(SocketServer.BaseRequestHandler):
>>    def handle(self):
>>        print self.client_address, now()
>>        print self.request
>>        time.sleep(5)
>>        while 1:
>>            data = self.request.recv(1024)
>>            if not data:
>>                break
>>            self.request.send('Echo=>%s at %s' % (data, now()))
>>        self.request.close()
>The code is wrong. It assumes that it is in charge of closing the
>socket (or that a closed socket will yield no data - which is just
>one way that you may find out a socket is closed).

Actually, this problem is caused by a bug in the SocketServer module
- the ThreadingMixin class overriding the process_request method means
that the ThreadingTCPServer.process_request() call returns as soon as
the Thread.start() call completes (instead of waiting for the request
to be handled as it would in a single thread). Then the handle_request
method on BaseServer closes the socket, which really should be closed
by the RequestHandler in this case (because there's no way for the
server to know when the thread finishes).

It was quite confusing when I got bitten by it, because (due to the
vagaries of thread scheduling) the error was occurring sometimes in
the recv() call and sometimes at the send(). That error message
doesn't help, although I guess that's happening at the OS level..

I fixed it by overriding handle_request like so:

    def handle_request(self):
        """Handle one request, possibly blocking."""
            request, client_address = self.get_request()
        except socket.error:
        if self.verify_request(request, client_address):
                self.process_request(request, client_address)
                self.handle_error(request, client_address)

So handle_request won't close the socket unless it gets an

And made sure the RequestHandler.handle method has a try... finally
block which closes the socket.

More info at SourceForge:


More information about the Python-list mailing list