bpo-36763: _Py_RunMain() doesn't call Py_Exit() anymore (GH-13390)

Py_Main() and _Py_RunMain() now return the exitcode rather than
calling Py_Exit(exitcode) when calling PyErr_Print() if the current
exception type is SystemExit.

* Add _Py_HandleSystemExit().
* Add pymain_exit_err_print().
* Add pymain_exit_print().
This commit is contained in:
Victor Stinner 2019-05-17 23:05:29 +02:00 committed by GitHub
parent bcfbbd7046
commit 12083284c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 117 additions and 63 deletions

View file

@ -585,23 +585,31 @@ print_error_text(PyObject *f, int offset, PyObject *text_obj)
PyFile_WriteString("^\n", f);
}
static void
handle_system_exit(void)
{
PyObject *exception, *value, *tb;
int exitcode = 0;
int
_Py_HandleSystemExit(int *exitcode_p)
{
int inspect = _PyInterpreterState_GET_UNSAFE()->core_config.inspect;
if (inspect) {
/* Don't exit if -i flag was given. This flag is set to 0
* when entering interactive mode for inspecting. */
return;
return 0;
}
if (!PyErr_ExceptionMatches(PyExc_SystemExit)) {
return 0;
}
PyObject *exception, *value, *tb;
PyErr_Fetch(&exception, &value, &tb);
fflush(stdout);
if (value == NULL || value == Py_None)
int exitcode = 0;
if (value == NULL || value == Py_None) {
goto done;
}
if (PyExceptionInstance_Check(value)) {
/* The error code should be in the `code' attribute. */
_Py_IDENTIFIER(code);
@ -615,8 +623,10 @@ handle_system_exit(void)
/* If we failed to dig out the 'code' attribute,
just let the else clause below print the error. */
}
if (PyLong_Check(value))
if (PyLong_Check(value)) {
exitcode = (int)PyLong_AsLong(value);
}
else {
PyObject *sys_stderr = _PySys_GetObjectId(&PyId_stderr);
/* We clear the exception here to avoid triggering the assertion
@ -633,6 +643,7 @@ handle_system_exit(void)
PySys_WriteStderr("\n");
exitcode = 1;
}
done:
/* Restore and clear the exception info, in order to properly decref
* the exception, value, and traceback. If we just exit instead,
@ -641,18 +652,28 @@ handle_system_exit(void)
*/
PyErr_Restore(exception, value, tb);
PyErr_Clear();
Py_Exit(exitcode);
/* NOTREACHED */
*exitcode_p = exitcode;
return 1;
}
static void
handle_system_exit(void)
{
int exitcode;
if (_Py_HandleSystemExit(&exitcode)) {
Py_Exit(exitcode);
}
}
void
PyErr_PrintEx(int set_sys_last_vars)
{
PyObject *exception, *v, *tb, *hook;
if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
handle_system_exit();
}
handle_system_exit();
PyErr_Fetch(&exception, &v, &tb);
if (exception == NULL)
return;
@ -686,10 +707,9 @@ PyErr_PrintEx(int set_sys_last_vars)
stack[2] = tb;
result = _PyObject_FastCall(hook, stack, 3);
if (result == NULL) {
handle_system_exit();
PyObject *exception2, *v2, *tb2;
if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
handle_system_exit();
}
PyErr_Fetch(&exception2, &v2, &tb2);
PyErr_NormalizeException(&exception2, &v2, &tb2);
/* It should not be possible for exception2 or v2