#32416: Apparent regression of #22414 from switching to ThreadedWSGIServer in
LiveServerTestCase (#20238)
--------------------------------+--------------------------------------
Reporter: Chris Jerdonek | Owner: nobody
Type: Uncategorized | Status: new
Component: Uncategorized | Version: 2.2
Severity: Normal | Resolution:
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
--------------------------------+--------------------------------------
Comment (by Chris Jerdonek):
Here is some more info I've collected. For each request, Django's
`ThreadedWSGIServer` calls its `process_request()` method, which lives in
CPython's `ThreadingMixIn`. In this method, `ThreadingMixIn` creates a new
thread with `target=self.process_request_thread`. The
`ThreadingMixIn.process_request_thread()` method looks like this:
{{{#!python
def process_request_thread(self, request, client_address):
"""Same as in BaseServer but as a thread.
In addition, exception handling is done here.
"""
try:
self.finish_request(request, client_address)
except Exception:
self.handle_error(request, client_address)
finally:
self.shutdown_request(request)
}}}
The `shutdown_request()` method has its implementation inside CPython's
`socketserver.TCPServer`. That method looks like this (`close_request()`
is also included here):
{{{#!python
def shutdown_request(self, request):
"""Called to shutdown and close an individual request."""
try:
#explicitly shutdown. socket.close() merely releases
#the socket and waits for GC to perform the actual close.
request.shutdown(socket.SHUT_WR)
except OSError:
pass #some platforms may raise ENOTCONN here
self.close_request(request)
def close_request(self, request):
"""Called to clean up an individual request."""
request.close()
}}}
Thus, if we wanted, database connections could perhaps be closed inside
`close_request()`. This could be done by adding a suitable implementation
to `ThreadedWSGIServer`, thus overriding
`socketserver.TCPServer.close_request()` .
The thread-sharing needed for SQLite could probably also be handled by
adding suitable method overrides to `ThreadedWSGIServer`.
By the way, since `LiveServerThread` currently creates its server with a
hard-coded class like this:
{{{#!python
def _create_server(self):
return ThreadedWSGIServer((self.host, self.port),
QuietWSGIRequestHandler, allow_reuse_address=False)
}}}
it would be easier for users if it instead got the class from a class
attribute, e.g.
{{{#!python
def _create_server(self):
return self.http_server_class((self.host, self.port),
QuietWSGIRequestHandler, allow_reuse_address=False)
}}}
That would let people patch `ThreadedWSGIServer` more easily, if needed.
This is similar to how `LiveServerTestCase` has a `server_thread_class`
class attribute currently set to `LiveServerThread` (with the attribute
added in #26976).
--
Ticket URL: <https://code.djangoproject.com/ticket/32416#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/067.349982e29ea5bcb0540e35d3e05d7908%40djangoproject.com.