This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author gwk
Recipients Melebius, gwk, r.david.murray
Date 2016-07-31.13:02:45
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1469970166.03.0.158432961874.issue27035@psf.upfronthosting.co.za>
In-reply-to
Content
The documentation for atexit.register clearly states that a SystemExit raised inside of the registered function is a special case:

'''
If an exception is raised during execution of the exit handlers, a traceback is printed (unless SystemExit is raised) and the exception information is saved. After all exit handlers have had a chance to run the last exception to be raised is re-raised.
'''

Python 2.7.11 behaves as described; Python 3.5.2 does not.

I believe there is a clear argument for allowing atexit functions to set an exit status code: Ultimately, it is the responsibility of the application programmer to return an appropriate code for all execution paths, and it is up to the programmer to decide what is appropriate. I can easily imagine cases where the atexit function encounters a critical error and the appropriate behavior is to return an error status to the parent process.

In many large systems, returning the correct code is the most critical behavior of a process, and so if atexit prevents the programmer from doing so then its utility is greatly diminished.

I disagree that calling _exit is "equally broken". Calling _exit completely breaks the atexit unwinding contract, and if an error code is necessary, then this is exactly what I am forced to do!

In my mind the correct behavior would be that the process exit code is determined from the last exception that occurs in the exit process.
- If the program begins exiting with 0, and then an atexit handler raises SystemExit(1), then code 1 should be returned.
- If the program begins exiting with 1, and then an atexit handler raises SystemExit(0), then code 0 should be returned (this may seem strange, but handlers can do all manner of strange things!).
- If successive handlers raise multiple exceptions, the last one determines the code.
- If the program is exiting with any code, and an exception other than SystemExit is raised, then we should return the code that would result from raising that exception in normal execution (usually 1).

I expect this last case to be most contentious, because it changes behavior for both python2 and python3. However I think it is desirable because it gives the handlers precise capabilities (and responsibilities) regarding process status. The point of atexit is to allow modules to execute code in a deferred manner; the design already specifies a 'last exception wins' policy, and the problem is that we are unnecessarily suppressing the exit code that would result from that last exception.
History
Date User Action Args
2016-07-31 13:02:46gwksetrecipients: + gwk, r.david.murray, Melebius
2016-07-31 13:02:46gwksetmessageid: <1469970166.03.0.158432961874.issue27035@psf.upfronthosting.co.za>
2016-07-31 13:02:45gwklinkissue27035 messages
2016-07-31 13:02:45gwkcreate