Opened 4 years ago

Closed 22 months ago

#32173 closed New feature (wontfix)

Autoreloader doesn't work with asyncio.

Reported by: Carlton Gibson Owned by: nobody
Component: Utilities Version: 3.1
Severity: Normal Keywords: async
Cc: Tom Forbes, Andrew Godwin Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

This is a follow-up to a discussion on the forum about the feasibility of using subprocess, rather than threads for the autoreloader.

The summary is that because of the way the autoreloader uses threading, it's not compatible with (most.many uses) of asyncio. (We end up trying to use the event loop from the main thread on the child thread, which Doesn't Work™).

This originally surfaced on Channels, we tried to fix it in Daphne, but this has lead to other issues, and we're going to have to revert that.

Other Channels users, looking at removing the dependency on Daphne there, have reported needing to re-implement reloading due to the threading behaviour.

Ultimately I think we have to resolve the threading issue in Django itself.

On the forum thread, Tom suggested that we might look into leveraging Hupper here. Assuming that would solve the threading issues (which seems like an empirical question just yet) I guess there'd need to a discussion about making that a required dependency or not, but it might be nice to settle on a solution here that's support more widely than just in Django.

Change History (4)

comment:1 by Carlton Gibson, 4 years ago

Keywords: async added

comment:2 by Mariusz Felisiak, 4 years ago

Triage Stage: UnreviewedAccepted

comment:3 by Carlton Gibson, 2 years ago

Part of the issue here is the structure of the auto-reloading: as it is currently, `runserver` is restarted in a subprocess but then runs Django, in `start_django()` in a thread, watching for changes in the main thread. (The multiple threads is what causes the issue here, with event loops being accessed on the wrong thread.)

A different structure would be start Django as a subprocess from the parent process, watch for changes in that same parent process, and restart the child process on a change. That's quite a big restructuring (but I think it might remove the need for the apps `ready_event` 🤔).

comment:4 by Carlton Gibson, 22 months ago

Resolution: wontfix
Status: newclosed

Over time this has faded away — I think dropping Python 3.6 support when that went EOL was the key. (As asyncio moved from get_event_loop to get_running_loop the tendency to get a reference to an event loop from a different thread faded.)

Auto-reloading works with the latest Daphne versions (>4). There may be lingering issues, but I think they can be resolved there.

Note: See TracTickets for help on using tickets.
Back to Top