New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
wsgiref does not call close() on iterable response #60424
Comments
When a WSGI application returns an iterable that has a .close() method, the server is supposed to call that method once the request has finished. The wsgiref server does not do this when a client disconnects from a streaming response. The attached script allows testing the .close() behavior of various wsgi servers (wsgiref, cherrypy, gevent, werkzeug, and gunicorn). wsgiref is the only one of the tested implementations that does not call .close(). |
This sounds like a reasonable expectation. Do you want to provide a patch? |
FYI, this looks like a bug in wsgiref.handlers.BaseHandler.finish_response(), which should probably be using a try/finally to ensure .close() gets called. (Which would catch a failed write() to the client.) I'm kind of amazed this has gone undetected this long, but I guess that either:
|
Patch attached. I ran into this while trying to figure out why close() wasn't being called while running the Django dev server, which inherits from wsgiref's BaseHandler. So I'm also surprised that it's gone unnoticed so long. Thanks for the quick attention and encouragement on this! |
Brent, could you possibly provide also a test?. Something to integrate with the standard testsuite that fails without your patch but passes with it. |
Your patch is trivial enough, I am OK to integrate it as is, but it would be nice to verify that we are not reintroducing this bug in the future. I know that writing a the test will be far more difficult that writing the patch. You can try :). Anyway I am OK to integrate current patch as is. Looks simple enough. The comment in "run()" is a bit scary, and we could call "self.close()" twice, with this patch, or call extra code after "self.close()" is called. I don't know it that would be an issue, I am not familiarized enough with WSGI. |
Hmmm. Wonders if finally finding this was prompted in part by recent post about this very issue. :-) http://blog.dscpl.com.au/2012/10/obligations-for-calling-close-on.html Also related is this issue from Django I highlighted long time ago. https://code.djangoproject.com/ticket/16241 I would have to look through Django code again but wondering if the issue there was in fact caused by underlying issue in standard library or whether would have needed to be separately fixed in Django still. |
You guessed it Graham! Bob Brewer pointed me to your post while I was fighting with this, which led me to testing the behavior under various servers and finding the wsgiref issue. Current Django trunk doesn't have its own finish_response anymore for the dev server; it's using the one on wsgiref's BaseHandler. So Django's problem should get fixed when wsgiref's does. I'm working on a test of the simpler case of ensuring that close() is called when any old exception is raised during the response. A test that actually sets up a socket and tests the client disconnecting would be a lot more complicated and a bit out of step with the current wsgi tests that all seem to use a socket-less mock. |
That's right, the Django bug report I filed was actually for Django 1.3, which didn't use wsgiref. I wasn't using Django 1.4 at the time so didn't bother to check its new implementation based on wsgiref. Instead I just assumed wsgiref would be right. Whoops. |
Updated patch with test attached. |
New changeset d5af1b235dab by Antoine Pitrou in branch '2.7': |
New changeset eef470032457 by Antoine Pitrou in branch '3.2': New changeset 2530acc092d8 by Antoine Pitrou in branch '3.3': New changeset cf3a739345c6 by Antoine Pitrou in branch 'default': |
Your patch is now committed, Brent, thank you! |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: