Opened 12 years ago
Closed 11 years ago
#19137 closed Bug (fixed)
runserver child started via autoreload won't always exit cleanly
Reported by: | santtu | Owned by: | nobody |
---|---|---|---|
Component: | Core (Management commands) | Version: | 1.4 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | yes | Patch needs improvement: | yes |
Easy pickings: | no | UI/UX: | no |
Description
When using django.utils.autoreload (for example, runserver with use_reloader option enabled) it is possible to get into a situation where you might think the server has been killed, but actually is not and is listening to the port.
Steps to reproduce:
- Start application, when use_reloader is enabled (manage.py runserver)
- Search for a pair of the manage.py processes (ps -aef --forest | grep runserver etc.), make a note of which is the parent and which is the child
- Kill the parent using command-line kill "kill -INT <parent pid>"
- Look at ps output, and you'll find the child still alive, and via lsof -i | grep LISTEN you can see it is still listening on the server port.
Normally if you use runserver from a terminal, pressing control-C will send SIGINT to the whole foreground process group. Both the parent and child will thus receive SIGINT and will exit cleanly.
If you however kill the *parent* only, the child will not receive any signal, and thus will happily keep running.
This is a bit of a bummer when doing test automation, which tries to clean up the test environment by killing the parent -- but the child won't go away, and keeping server port reserved.
It is possible to do a semi-work-around by spawning runserver in its own process group, but it requires some careful environment crafting (and I haven't been able to get it reliably working on macos -- there are apparently some semantic differences in setpgrp wrt/ linux and macos). And of course is hardly obvious for anyone encountering this problem for the first time.
I have a patch for this and I'll make a pull request and link to that when I have a ticket id..
Change History (8)
comment:1 by , 12 years ago
comment:3 by , 12 years ago
Has patch: | set |
---|---|
Needs tests: | set |
comment:4 by , 12 years ago
Triage Stage: | Unreviewed → Accepted |
---|---|
Type: | Uncategorized → Bug |
comment:5 by , 12 years ago
#16982 was closed as duplicate of this one.
Feedback about how things work on Mac OS X and Windows once the PR has been applied is welcome.
comment:6 by , 12 years ago
This patch doesn't seem to work on windows.
On a quick search I found: http://danielkaes.wordpress.com/2009/06/04/how-to-catch-kill-events-with-python/ (the last comment implies that killing a process with the task manager in windows will kill all threads, giving no further chance to actually treat the exception, in which case, a signal-based approach won't work on windows).
comment:7 by , 11 years ago
Patch needs improvement: | set |
---|
Setting patch needs improvement since it doesn't work on Windows according to the previous comment.
comment:8 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
BTW, there is also another obvious work-around when doing test automation: disable autoreloader.