bpo-36142: Rework error reporting in pymain_main() (GH-12113)
Add a new _Py_INIT_EXIT() macro to be able to exit Python with an
exitcode using _PyInitError API. Rewrite function calls by
pymain_main() to use _PyInitError.
Changes:
* Remove _PyMain.err and _PyMain.status field
* Add _Py_INIT_EXIT() macro and _PyInitError.exitcode field.
* Rename _Py_FatalInitError() to _Py_ExitInitError().
diff --git a/Include/cpython/coreconfig.h b/Include/cpython/coreconfig.h
index f7ac3f9..2ce99b2 100644
--- a/Include/cpython/coreconfig.h
+++ b/Include/cpython/coreconfig.h
@@ -11,6 +11,7 @@
const char *prefix;
const char *msg;
int user_err;
+ int exitcode;
} _PyInitError;
/* Almost all errors causing Python initialization to fail */
@@ -22,16 +23,18 @@
#endif
#define _Py_INIT_OK() \
- (_PyInitError){.prefix = NULL, .msg = NULL, .user_err = 0}
+ (_PyInitError){.prefix = NULL, .msg = NULL, .user_err = 0, .exitcode = -1}
#define _Py_INIT_ERR(MSG) \
- (_PyInitError){.prefix = _Py_INIT_GET_FUNC(), .msg = (MSG), .user_err = 0}
+ (_PyInitError){.prefix = _Py_INIT_GET_FUNC(), .msg = (MSG), .user_err = 0, .exitcode = -1}
/* Error that can be fixed by the user like invalid input parameter.
Don't abort() the process on such error. */
#define _Py_INIT_USER_ERR(MSG) \
- (_PyInitError){.prefix = _Py_INIT_GET_FUNC(), .msg = (MSG), .user_err = 1}
+ (_PyInitError){.prefix = _Py_INIT_GET_FUNC(), .msg = (MSG), .user_err = 1, .exitcode = -1}
#define _Py_INIT_NO_MEMORY() _Py_INIT_USER_ERR("memory allocation failed")
+#define _Py_INIT_EXIT(EXITCODE) \
+ (_PyInitError){.prefix = NULL, .msg = NULL, .user_err = 0, .exitcode = (EXITCODE)}
#define _Py_INIT_FAILED(err) \
- (err.msg != NULL)
+ (err.msg != NULL || err.exitcode != -1)
/* _PyCoreConfig */
diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h
index a3fdeef..3bffc80 100644
--- a/Include/cpython/pylifecycle.h
+++ b/Include/cpython/pylifecycle.h
@@ -39,7 +39,7 @@
PyAPI_FUNC(_PyInitError) _Py_InitializeFromConfig(
const _PyCoreConfig *config);
-PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalInitError(_PyInitError err);
+PyAPI_FUNC(void) _Py_NO_RETURN _Py_ExitInitError(_PyInitError err);
/* Py_PyAtExit is for the atexit module, Py_AtExit is for low-level
* exit functions.