[Python-Dev] SocketServer and UserDict patches

Guido van Rossum guido@digicool.com
Tue, 10 Apr 2001 15:45:35 -0500


> On Tue, 10 Apr 2001, Guido van Rossum wrote:
> > > 1.  UserDict.get(), .update(), and .setdefault()
> [...]
> > I agree with the gist of this -- it should have been done the way you
> > propose.
> [...]
> > But can you guarantee that fixing this so late in the release cycle
> > won't break anybody's code?
> 
> Right, obviously i can't.  Here are some thoughts:
> (Nonetheless i do agree it's a bit late to notice this.)
> 
>     1.  All the standard tests pass with this change (though
>         of course that's a small sample).
> 
>     2.  It's hard to imagine someone's code depending on this
>         particular bug (i think i can justify calling it a bug).
>         Anyone who wrote a UserDict-derived class that actually
>         intended to use "get" most likely had to work around it
>         anyway, to get any reasonable sort of result.
> 
>     3.  Would you consider allowing the addition of a get()
>         method just to cgi.SvFormContentDict to fix its behaviour?
>         (The broken get() behaviour was present for this particular
>         class in 2.0 but not in 1.5.2.)

Let's just fix this after releasing 2.1, OK?  As you say, it's
unlikely that this affects anybody one way or the other, and right now
I'm for stability in favor of fixing warts (believe me, I have a few
other favorite warts that I won't fix before releasing 2.1 :-).

> 
> > > 2.  SocketServer.StreamRequestHandler
> [...]
> > I don't think this is the right solution.  A principle I like very
> > much to keep my head clear about closing files is "whoever opens it
> > closes it".  The request/connection socket is created by a different
> > class, so should really be closed there.
> 
> Good point.  How about adding to BaseServer.handle_request instead?
> 
>     def handle_request(self):
>         """Handle one request, possibly blocking."""
>         try:
>             request, client_address = self.get_request()
>         except socket.error:
>             return
>         if self.verify_request(request, client_address):
>             try:
>                 self.process_request(request, client_address)
>             except:
>                 self.handle_error(request, client_address)
>   +     request.close()

Alas, this is still at the wrong level.  The get_request() method is
overridable (e.g. by the UDPServer class) and the request that it
returns may not have a close method.  The best I can come up with is
to add an empty method self.close_request(request) to the base class,
call it in handle_request(), and override it to call request.close()
in the TCPServer class.

> I forgot to mention that this is a testable and observable fix
> (Netscape gets stuck in Linux and IE gets stuck in Win2K without
> the fix, and both work properly when i make this fix.)

I believe you -- I've noticed weird slownesses when using
SimpleHTTPServer.

> Note that this makes explicit the division of responsibilities
> that, if the request handler wants to continue dealing with the
> request connection after its constructor returns (as in the
> case of the forking and threading variants), it must duplicate
> its own copy of the file descriptor (which it already does).
> I think this is good, as then each file descriptor can be
> associated with a clear owner.

No argument there!

--Guido van Rossum (home page: http://www.python.org/~guido/)