Refs #31040, Refs #31224 -- Prevented cycles in exceptions chain.

Async exception handling was raising an exception that was creating a
cycle in the exception chain (by re-raising an exception in
sync_to_async that was already being handled).

Thanks Chris Jerdonek for detailed analysis.
This commit is contained in:
Mariusz Felisiak 2020-05-28 13:05:15 +02:00 committed by GitHub
parent fa58450a9a
commit d94a9aa055
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 10 additions and 2 deletions

View File

@ -179,6 +179,8 @@ class BaseHandler:
response = wrapped_callback(request, *callback_args, **callback_kwargs) response = wrapped_callback(request, *callback_args, **callback_kwargs)
except Exception as e: except Exception as e:
response = self.process_exception_by_middleware(e, request) response = self.process_exception_by_middleware(e, request)
if response is None:
raise
# Complain if the view returned None (a common error). # Complain if the view returned None (a common error).
self.check_response(response, callback) self.check_response(response, callback)
@ -200,6 +202,8 @@ class BaseHandler:
response = response.render() response = response.render()
except Exception as e: except Exception as e:
response = self.process_exception_by_middleware(e, request) response = self.process_exception_by_middleware(e, request)
if response is None:
raise
return response return response
@ -230,6 +234,8 @@ class BaseHandler:
self.process_exception_by_middleware, self.process_exception_by_middleware,
thread_sensitive=True, thread_sensitive=True,
)(e, request) )(e, request)
if response is None:
raise
# Complain if the view returned None or an uncalled coroutine. # Complain if the view returned None or an uncalled coroutine.
self.check_response(response, callback) self.check_response(response, callback)
@ -258,6 +264,8 @@ class BaseHandler:
self.process_exception_by_middleware, self.process_exception_by_middleware,
thread_sensitive=True, thread_sensitive=True,
)(e, request) )(e, request)
if response is None:
raise
# Make sure the response is not a coroutine # Make sure the response is not a coroutine
if asyncio.iscoroutine(response): if asyncio.iscoroutine(response):
@ -323,13 +331,13 @@ class BaseHandler:
def process_exception_by_middleware(self, exception, request): def process_exception_by_middleware(self, exception, request):
""" """
Pass the exception to the exception middleware. If no middleware Pass the exception to the exception middleware. If no middleware
return a response for this exception, raise it. return a response for this exception, return None.
""" """
for middleware_method in self._exception_middleware: for middleware_method in self._exception_middleware:
response = middleware_method(request, exception) response = middleware_method(request, exception)
if response: if response:
return response return response
raise return None
def reset_urlconf(sender, **kwargs): def reset_urlconf(sender, **kwargs):