Skip to content
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

Closed
btubbs mannequin opened this issue Oct 13, 2012 · 13 comments
Closed

wsgiref does not call close() on iterable response #60424

btubbs mannequin opened this issue Oct 13, 2012 · 13 comments
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@btubbs
Copy link
Mannequin

btubbs mannequin commented Oct 13, 2012

BPO 16220
Nosy @jcea, @pjeby, @pitrou
Files
  • sleepy_app.py: test script
  • wsgiref_close.patch
  • wsgiref_close_plus_test.patch
  • 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:

    assignee = None
    closed_at = <Date 2012-10-21.12:17:46.643>
    created_at = <Date 2012-10-13.21:00:20.662>
    labels = ['type-bug', 'library']
    title = 'wsgiref does not call close() on iterable response'
    updated_at = <Date 2012-10-21.12:17:46.642>
    user = 'https://bugs.python.org/btubbs'

    bugs.python.org fields:

    activity = <Date 2012-10-21.12:17:46.642>
    actor = 'pitrou'
    assignee = 'none'
    closed = True
    closed_date = <Date 2012-10-21.12:17:46.643>
    closer = 'pitrou'
    components = ['Library (Lib)']
    creation = <Date 2012-10-13.21:00:20.662>
    creator = 'btubbs'
    dependencies = []
    files = ['27555', '27561', '27608']
    hgrepos = []
    issue_num = 16220
    keywords = ['patch']
    message_count = 13.0
    messages = ['172830', '172831', '172841', '172858', '172937', '172939', '172940', '172945', '172952', '173234', '173442', '173445', '173446']
    nosy_count = 6.0
    nosy_names = ['jcea', 'pje', 'pitrou', 'grahamd', 'python-dev', 'btubbs']
    pr_nums = []
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue16220'
    versions = ['Python 2.7', 'Python 3.2', 'Python 3.3', 'Python 3.4']

    @btubbs
    Copy link
    Mannequin Author

    btubbs mannequin commented Oct 13, 2012

    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().

    @btubbs btubbs mannequin added the stdlib Python modules in the Lib dir label Oct 13, 2012
    @btubbs btubbs mannequin changed the title wsgiref does not call close() on iterable response when client wsgiref does not call close() on iterable response Oct 13, 2012
    @pitrou
    Copy link
    Member

    pitrou commented Oct 13, 2012

    This sounds like a reasonable expectation. Do you want to provide a patch?

    @pitrou pitrou added the type-bug An unexpected behavior, bug, or error label Oct 13, 2012
    @pjeby
    Copy link
    Mannequin

    pjeby mannequin commented Oct 14, 2012

    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:

    1. other servers are probably catching errors from .run() and closing,
    2. they're not using BaseHandler in their implementation, or
    3. most apps don't have anything that essential in close() and/or the clients don't disconnect that often. ;-)

    @btubbs
    Copy link
    Mannequin Author

    btubbs mannequin commented Oct 14, 2012

    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!

    @jcea
    Copy link
    Member

    jcea commented Oct 15, 2012

    Brent, could you possibly provide also a test?. Something to integrate with the standard testsuite that fails without your patch but passes with it.

    @jcea
    Copy link
    Member

    jcea commented Oct 15, 2012

    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.

    @grahamd
    Copy link
    Mannequin

    grahamd mannequin commented Oct 15, 2012

    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.

    @btubbs
    Copy link
    Mannequin Author

    btubbs mannequin commented Oct 15, 2012

    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.

    @grahamd
    Copy link
    Mannequin

    grahamd mannequin commented Oct 15, 2012

    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.

    @btubbs
    Copy link
    Mannequin Author

    btubbs mannequin commented Oct 18, 2012

    Updated patch with test attached.

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Oct 21, 2012

    New changeset d5af1b235dab by Antoine Pitrou in branch '2.7':
    Issue bpo-16220: wsgiref now always calls close() on an iterable response.
    http://hg.python.org/cpython/rev/d5af1b235dab

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Oct 21, 2012

    New changeset eef470032457 by Antoine Pitrou in branch '3.2':
    Issue bpo-16220: wsgiref now always calls close() on an iterable response.
    http://hg.python.org/cpython/rev/eef470032457

    New changeset 2530acc092d8 by Antoine Pitrou in branch '3.3':
    Issue bpo-16220: wsgiref now always calls close() on an iterable response.
    http://hg.python.org/cpython/rev/2530acc092d8

    New changeset cf3a739345c6 by Antoine Pitrou in branch 'default':
    Issue bpo-16220: wsgiref now always calls close() on an iterable response.
    http://hg.python.org/cpython/rev/cf3a739345c6

    @pitrou
    Copy link
    Member

    pitrou commented Oct 21, 2012

    Your patch is now committed, Brent, thank you!

    @pitrou pitrou closed this as completed Oct 21, 2012
    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    2 participants