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

Connection won't be closed if raise exception in AsyncHttpConsumer::handle() #1350

Open
kmiku7 opened this issue Sep 11, 2019 · 5 comments · May be fixed by #2131
Open

Connection won't be closed if raise exception in AsyncHttpConsumer::handle() #1350

kmiku7 opened this issue Sep 11, 2019 · 5 comments · May be fixed by #2131
Assignees
Labels

Comments

@kmiku7
Copy link

kmiku7 commented Sep 11, 2019

Connection won't be closed when exception occurred in AsyncHttpConsumer::handle() and handle() have sent nothing using send() or send_body(). So client will be hanged there until timeout, with nothing received. In server-side, there is no exception traceback/information logged.
We can reproduce this case using following codes:

class DemoHttpConsumer(AsyncHttpConsumer):
  async def handle(self, body):
    raise ValueError()

I have read codes, it's because the exception occurred in handle() is ignore in

async def http_request(self, message):
"""
Async entrypoint - concatenates body fragments and hands off control
to ``self.handle`` when the body has been completely received.
"""
if "body" in message:
self.body.append(message["body"])
if not message.get("more_body"):
try:
await self.handle(b"".join(self.body))
finally:
await self.disconnect()
raise StopConsumer()

In finally statements, exception was ignored by raise StopConsumer(). So all coroutines will be waiting continues.

If send() something in AsyncHttpConsumer::handle(). Daphne will send {"type": "http.disconnect"} message in here:
https://github.com/django/daphne/blob/333f4644d1a5a167c85eca967a52e4e10a7db0bd/daphne/http_protocol.py#L257-L258

            if not message.get("more_body", False):
                self.finish()
                logger.debug("HTTP response complete for %s", self.client_addr)

which make all coroutines exit.

Now I am selecting a web-socket framework used in my company's project.
Because I am a novice in python asynchronies programming and channels, I'm sorry can't submit a patch to fix it. So can you fix this problem soon?

@carltongibson
Copy link
Member

OK, thanks for the report. There are a bunch of issues around AsyncHttpConsumer, which is next on the list now. I'm hoping to have some time for it at the DjangoCon sprints next week.

@carltongibson carltongibson self-assigned this Dec 2, 2019
@IronJam11
Copy link
Contributor

@carltongibson, if it is still open, i would like to work on this one

@carltongibson
Copy link
Member

@IronJam11 You're welcome to look at it of course.

@IronJam11
Copy link
Contributor

I had a small question, when exactly is the http_disconnect function called in channels.generic.http.py

@carltongibson
Copy link
Member

@IronJam11 It's called in the base class AsyncConsumer.dispatch. You might want to review the Consumers docs to make sure you're clear on the behaviour. Then read AsyncConsumer.__call__ to see how the ASGI spec is implemented. The consumer is the ASGI application (potentially wrapped by other applications, but you can ignore that).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
3 participants