The root difference here is not actually associated with both signals and atexit, but rather with a change in the behavior of sys.exit
.
Prior to 2.6.5, sys.exit
(more precisely, SystemExit caught at the top level) will force the interpreter to exit; if the threads are still running, they will be terminated, as in POSIX threads.
Around 2.6.5, the behavior has changed: the sys.exit
effect now essentially coincides with the return from the main function of the program. When you do this - in both versions - the interpreter waits until all threads are connected before exiting.
The corresponding change is that Py_Finalize
now calls wait_for_thread_shutdown()
near the vertex where it was not there before.
This behavioral change seems to be wrong, primarily because it no longer functions as documented, but simply: "Quit Python". The practical effect is not exiting Python, but simply exiting the stream. (As a note, sys.exit
never exited Python when called from another thread, but this implicit discrepancy with the documented behavior does not justify much more.)
I see the attractiveness of the new behavior: instead of two ways to exit the main thread ("exit and wait for threads" and "exit immediately"), there is only one, since sys.exit is essentially identical to the simple returning from the top function. However, this is a terrific change and diverges from documented behavior that far outweighs this.
Due to this change, after sys.exit
from the signal handler above, the interpreter sits around waiting for the threads to exit and then starts the atexit
handlers after that. Since it is the handler itself that informs the threads about the exit, the result is a dead end.
Glenn Maynard Sep 21 '10 at 23:13 2010-09-21 23:13
source share