diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2017-11-15 15:48:08 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-15 15:48:08 -0800 |
commit | f7e5b56c37eb859e225e886c79c5d742c567ee95 (patch) | |
tree | 7d722ca38595aaa68e02a1ee1ea53e17a54b0188 /Python/pylifecycle.c | |
parent | 43605e6bfa8d49612df4a38460d063d6ba781906 (diff) | |
download | cpython-git-f7e5b56c37eb859e225e886c79c5d742c567ee95.tar.gz |
bpo-32030: Split Py_Main() into subfunctions (#4399)
* Don't use "Python runtime" anymore to parse command line options or
to get environment variables: pymain_init() is now a strict
separation.
* Use an error message rather than "crashing" directly with
Py_FatalError(). Limit the number of calls to Py_FatalError(). It
prepares the code to handle errors more nicely later.
* Warnings options (-W, PYTHONWARNINGS) and "XOptions" (-X) are now
only added to the sys module once Python core is properly
initialized.
* _PyMain is now the well identified owner of some important strings
like: warnings options, XOptions, and the "program name". The
program name string is now properly freed at exit.
pymain_free() is now responsible to free the "command" string.
* Rename most methods in Modules/main.c to use a "pymain_" prefix to
avoid conflits and ease debug.
* Replace _Py_CommandLineDetails_INIT with memset(0)
* Reorder a lot of code to fix the initialization ordering. For
example, initializing standard streams now comes before parsing
PYTHONWARNINGS.
* Py_Main() now handles errors when adding warnings options and
XOptions.
* Add _PyMem_GetDefaultRawAllocator() private function.
* Cleanup _PyMem_Initialize(): remove useless global constants: move
them into _PyMem_Initialize().
* Call _PyRuntime_Initialize() as soon as possible:
_PyRuntime_Initialize() now returns an error message on failure.
* Add _PyInitError structure and following macros:
* _Py_INIT_OK()
* _Py_INIT_ERR(msg)
* _Py_INIT_USER_ERR(msg): "user" error, don't abort() in that case
* _Py_INIT_FAILED(err)
Diffstat (limited to 'Python/pylifecycle.c')
-rw-r--r-- | Python/pylifecycle.c | 394 |
1 files changed, 261 insertions, 133 deletions
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 8817be1c41..66cc711137 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -53,11 +53,11 @@ extern wchar_t *Py_GetPath(void); extern grammar _PyParser_Grammar; /* From graminit.c */ /* Forward */ -static void initmain(PyInterpreterState *interp); -static int initfsencoding(PyInterpreterState *interp); -static void initsite(void); +static _PyInitError add_main_module(PyInterpreterState *interp); +static _PyInitError initfsencoding(PyInterpreterState *interp); +static _PyInitError initsite(void); static int initstdio(void); -static void initsigs(void); +static _PyInitError initsigs(void); static void call_py_exitfuncs(void); static void wait_for_thread_shutdown(void); static void call_ll_exitfuncs(void); @@ -66,7 +66,7 @@ extern int _PyStructSequence_Init(void); extern void _PyUnicode_Fini(void); extern int _PyLong_Init(void); extern void PyLong_Fini(void); -extern int _PyFaulthandler_Init(void); +extern _PyInitError _PyFaulthandler_Init(void); extern void _PyFaulthandler_Fini(void); extern void _PyHash_Fini(void); extern int _PyTraceMalloc_Init(void); @@ -76,9 +76,9 @@ extern void _Py_ReadyTypes(void); extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *); extern void _PyGILState_Fini(void); -_PyRuntimeState _PyRuntime = {0, 0}; +_PyRuntimeState _PyRuntime = _PyRuntimeState_INIT; -void +_PyInitError _PyRuntime_Initialize(void) { /* XXX We only initialize once in the process, which aligns with @@ -88,10 +88,12 @@ _PyRuntime_Initialize(void) This is because the runtime state is not properly finalized currently. */ static int initialized = 0; - if (initialized) - return; + if (initialized) { + return _Py_INIT_OK(); + } initialized = 1; - _PyRuntimeState_Init(&_PyRuntime); + + return _PyRuntimeState_Init(&_PyRuntime); } void @@ -282,43 +284,44 @@ get_locale_encoding(void) #endif } -static void +/* Return NULL on success, or return an error message on failure */ +static _PyInitError initimport(PyInterpreterState *interp, PyObject *sysmod) { PyObject *importlib; PyObject *impmod; PyObject *value; + _PyInitError err; /* Import _importlib through its frozen version, _frozen_importlib. */ if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) { - Py_FatalError("Py_Initialize: can't import _frozen_importlib"); + return _Py_INIT_ERR("can't import _frozen_importlib"); } else if (Py_VerboseFlag) { PySys_FormatStderr("import _frozen_importlib # frozen\n"); } importlib = PyImport_AddModule("_frozen_importlib"); if (importlib == NULL) { - Py_FatalError("Py_Initialize: couldn't get _frozen_importlib from " - "sys.modules"); + return _Py_INIT_ERR("couldn't get _frozen_importlib from sys.modules"); } interp->importlib = importlib; Py_INCREF(interp->importlib); interp->import_func = PyDict_GetItemString(interp->builtins, "__import__"); if (interp->import_func == NULL) - Py_FatalError("Py_Initialize: __import__ not found"); + return _Py_INIT_ERR("__import__ not found"); Py_INCREF(interp->import_func); /* Import the _imp module */ impmod = PyInit_imp(); if (impmod == NULL) { - Py_FatalError("Py_Initialize: can't import _imp"); + return _Py_INIT_ERR("can't import _imp"); } else if (Py_VerboseFlag) { PySys_FormatStderr("import _imp # builtin\n"); } if (_PyImport_SetModuleString("_imp", impmod) < 0) { - Py_FatalError("Py_Initialize: can't save _imp to sys.modules"); + return _Py_INIT_ERR("can't save _imp to sys.modules"); } /* Install importlib as the implementation of import */ @@ -330,15 +333,21 @@ initimport(PyInterpreterState *interp, PyObject *sysmod) } if (value == NULL) { PyErr_Print(); - Py_FatalError("Py_Initialize: importlib install failed"); + return _Py_INIT_ERR("importlib install failed"); } Py_DECREF(value); Py_DECREF(impmod); - _PyImportZip_Init(); + err = _PyImportZip_Init(); + if (_Py_INIT_FAILED(err)) { + return err; + } + + return _Py_INIT_OK(); } -static void +/* Return NULL on success, or return an error message on failure */ +static _PyInitError initexternalimport(PyInterpreterState *interp) { PyObject *value; @@ -346,9 +355,10 @@ initexternalimport(PyInterpreterState *interp) "_install_external_importers", ""); if (value == NULL) { PyErr_Print(); - Py_FatalError("Py_EndInitialization: external importer setup failed"); + return _Py_INIT_ERR("external importer setup failed"); } Py_DECREF(value); + return _Py_INIT_OK(); } /* Helper functions to better handle the legacy C locale @@ -613,13 +623,16 @@ _Py_SetLocaleFromEnv(int category) * Any code invoked from this function should *not* assume it has access * to the Python C API (unless the API is explicitly listed as being * safe to call without calling Py_Initialize first) + * + * Return NULL on success, or return an error message on failure. */ /* TODO: Progressively move functionality from Py_BeginInitialization to * Py_ReadConfig and Py_EndInitialization */ -void _Py_InitializeCore(const _PyCoreConfig *config) +_PyInitError +_Py_InitializeCore(const _PyCoreConfig *config) { PyInterpreterState *interp; PyThreadState *tstate; @@ -627,18 +640,26 @@ void _Py_InitializeCore(const _PyCoreConfig *config) char *p; _PyCoreConfig core_config = _PyCoreConfig_INIT; _PyMainInterpreterConfig preinit_config = _PyMainInterpreterConfig_INIT; + _PyInitError err; - _PyRuntime_Initialize(); + err = _PyRuntime_Initialize(); + if (_Py_INIT_FAILED(err)) { + return err; + } if (config != NULL) { core_config = *config; } + if (_PyMem_SetupAllocators(core_config.allocator) < 0) { + return _Py_INIT_ERR("Unknown PYTHONMALLOC allocator"); + } + if (_PyRuntime.initialized) { - Py_FatalError("Py_InitializeCore: main interpreter already initialized"); + return _Py_INIT_ERR("main interpreter already initialized"); } if (_PyRuntime.core_initialized) { - Py_FatalError("Py_InitializeCore: runtime core already initialized"); + return _Py_INIT_ERR("runtime core already initialized"); } /* Py_Finalize leaves _Py_Finalizing set in order to help daemon @@ -652,13 +673,6 @@ void _Py_InitializeCore(const _PyCoreConfig *config) */ _PyRuntime.finalizing = NULL; - if (_PyMem_SetupAllocators(core_config.allocator) < 0) { - fprintf(stderr, - "Error in PYTHONMALLOC: unknown allocator \"%s\"!\n", - core_config.allocator); - exit(1); - } - #ifndef MS_WINDOWS /* Set up the LC_CTYPE locale, so we can obtain the locale's charset without having to switch @@ -692,7 +706,11 @@ void _Py_InitializeCore(const _PyCoreConfig *config) set_flag(&Py_LegacyWindowsStdioFlag, p); #endif - _Py_HashRandomization_Init(&core_config); + err = _Py_HashRandomization_Init(&core_config); + if (_Py_INIT_FAILED(err)) { + return err; + } + if (!core_config.use_hash_seed || core_config.hash_seed) { /* Random or non-zero hash seed */ Py_HashRandomizationFlag = 1; @@ -701,13 +719,13 @@ void _Py_InitializeCore(const _PyCoreConfig *config) _PyInterpreterState_Enable(&_PyRuntime); interp = PyInterpreterState_New(); if (interp == NULL) - Py_FatalError("Py_InitializeCore: can't make main interpreter"); + return _Py_INIT_ERR("can't make main interpreter"); interp->core_config = core_config; interp->config = preinit_config; tstate = PyThreadState_New(interp); if (tstate == NULL) - Py_FatalError("Py_InitializeCore: can't make first thread"); + return _Py_INIT_ERR("can't make first thread"); (void) PyThreadState_Swap(tstate); /* We can't call _PyEval_FiniThreads() in Py_FinalizeEx because @@ -722,46 +740,50 @@ void _Py_InitializeCore(const _PyCoreConfig *config) _Py_ReadyTypes(); if (!_PyFrame_Init()) - Py_FatalError("Py_InitializeCore: can't init frames"); + return _Py_INIT_ERR("can't init frames"); if (!_PyLong_Init()) - Py_FatalError("Py_InitializeCore: can't init longs"); + return _Py_INIT_ERR("can't init longs"); if (!PyByteArray_Init()) - Py_FatalError("Py_InitializeCore: can't init bytearray"); + return _Py_INIT_ERR("can't init bytearray"); if (!_PyFloat_Init()) - Py_FatalError("Py_InitializeCore: can't init float"); + return _Py_INIT_ERR("can't init float"); PyObject *modules = PyDict_New(); if (modules == NULL) - Py_FatalError("Py_InitializeCore: can't make modules dictionary"); + return _Py_INIT_ERR("can't make modules dictionary"); interp->modules = modules; - sysmod = _PySys_BeginInit(); - if (sysmod == NULL) - Py_FatalError("Py_InitializeCore: can't initialize sys"); + err = _PySys_BeginInit(&sysmod); + if (_Py_INIT_FAILED(err)) { + return err; + } + interp->sysdict = PyModule_GetDict(sysmod); - if (interp->sysdict == NULL) - Py_FatalError("Py_InitializeCore: can't initialize sys dict"); + if (interp->sysdict == NULL) { + return _Py_INIT_ERR("can't initialize sys dict"); + } + Py_INCREF(interp->sysdict); PyDict_SetItemString(interp->sysdict, "modules", modules); _PyImport_FixupBuiltin(sysmod, "sys", modules); /* Init Unicode implementation; relies on the codec registry */ if (_PyUnicode_Init() < 0) - Py_FatalError("Py_InitializeCore: can't initialize unicode"); + return _Py_INIT_ERR("can't initialize unicode"); if (_PyStructSequence_Init() < 0) - Py_FatalError("Py_InitializeCore: can't initialize structseq"); + return _Py_INIT_ERR("can't initialize structseq"); bimod = _PyBuiltin_Init(); if (bimod == NULL) - Py_FatalError("Py_InitializeCore: can't initialize builtins modules"); + return _Py_INIT_ERR("can't initialize builtins modules"); _PyImport_FixupBuiltin(bimod, "builtins", modules); interp->builtins = PyModule_GetDict(bimod); if (interp->builtins == NULL) - Py_FatalError("Py_InitializeCore: can't initialize builtins dict"); + return _Py_INIT_ERR("can't initialize builtins dict"); Py_INCREF(interp->builtins); /* initialize builtin exceptions */ @@ -771,25 +793,35 @@ void _Py_InitializeCore(const _PyCoreConfig *config) infrastructure for the io module in place. */ pstderr = PyFile_NewStdPrinter(fileno(stderr)); if (pstderr == NULL) - Py_FatalError("Py_InitializeCore: can't set preliminary stderr"); + return _Py_INIT_ERR("can't set preliminary stderr"); _PySys_SetObjectId(&PyId_stderr, pstderr); PySys_SetObject("__stderr__", pstderr); Py_DECREF(pstderr); - _PyImport_Init(); + err = _PyImport_Init(); + if (_Py_INIT_FAILED(err)) { + return err; + } - _PyImportHooks_Init(); + err = _PyImportHooks_Init(); + if (_Py_INIT_FAILED(err)) { + return err; + } /* Initialize _warnings. */ _PyWarnings_Init(); /* This call sets up builtin and frozen import support */ if (!interp->core_config._disable_importlib) { - initimport(interp, sysmod); + err = initimport(interp, sysmod); + if (_Py_INIT_FAILED(err)) { + return err; + } } /* Only when we get here is the runtime core fully initialized */ _PyRuntime.core_initialized = 1; + return _Py_INIT_OK(); } /* Read configuration settings from standard locations @@ -802,16 +834,18 @@ void _Py_InitializeCore(const _PyCoreConfig *config) * * More advanced selective initialization tricks are possible by calling * this function multiple times with various preconfigured settings. + * + * Return NULL on success, or return an error message on failure. */ -int _Py_ReadMainInterpreterConfig(_PyMainInterpreterConfig *config) +_PyInitError +_Py_ReadMainInterpreterConfig(_PyMainInterpreterConfig *config) { /* Signal handlers are installed by default */ if (config->install_signal_handlers < 0) { config->install_signal_handlers = 1; } - - return 0; + return _Py_INIT_OK(); } /* Update interpreter state based on supplied configuration settings @@ -824,26 +858,30 @@ int _Py_ReadMainInterpreterConfig(_PyMainInterpreterConfig *config) * initialized or without a valid current thread state is a fatal error. * Other errors should be reported as normal Python exceptions with a * non-zero return code. + * + * Return NULL on success, or return an error message on failure. */ -int _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) +_PyInitError +_Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) { PyInterpreterState *interp; PyThreadState *tstate; + _PyInitError err; if (!_PyRuntime.core_initialized) { - Py_FatalError("Py_InitializeMainInterpreter: runtime core not initialized"); + return _Py_INIT_ERR("runtime core not initialized"); } if (_PyRuntime.initialized) { - Py_FatalError("Py_InitializeMainInterpreter: main interpreter already initialized"); + return _Py_INIT_ERR("main interpreter already initialized"); } /* Get current thread state and interpreter pointer */ tstate = PyThreadState_GET(); if (!tstate) - Py_FatalError("Py_InitializeMainInterpreter: failed to read thread state"); + return _Py_INIT_ERR("failed to read thread state"); interp = tstate->interp; if (!interp) - Py_FatalError("Py_InitializeMainInterpreter: failed to get interpreter"); + return _Py_INIT_ERR("failed to get interpreter"); /* Now finish configuring the main interpreter */ interp->config = *config; @@ -855,12 +893,12 @@ int _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) * or pure Python code in the standard library won't work. */ _PyRuntime.initialized = 1; - return 0; + return _Py_INIT_OK(); } /* TODO: Report exceptions rather than fatal errors below here */ if (_PyTime_Init() < 0) - Py_FatalError("Py_InitializeMainInterpreter: can't initialize time"); + return _Py_INIT_ERR("can't initialize time"); /* Finish setting up the sys module and import system */ /* GetPath may initialize state that _PySys_EndInit locks @@ -868,26 +906,40 @@ int _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) /* TODO: Call Py_GetPath() in Py_ReadConfig, rather than here */ PySys_SetPath(Py_GetPath()); if (_PySys_EndInit(interp->sysdict) < 0) - Py_FatalError("Py_InitializeMainInterpreter: can't finish initializing sys"); - initexternalimport(interp); + return _Py_INIT_ERR("can't finish initializing sys"); + err = initexternalimport(interp); + if (_Py_INIT_FAILED(err)) { + return err; + } /* initialize the faulthandler module */ - if (_PyFaulthandler_Init()) - Py_FatalError("Py_InitializeMainInterpreter: can't initialize faulthandler"); + err = _PyFaulthandler_Init(); + if (_Py_INIT_FAILED(err)) { + return err; + } - if (initfsencoding(interp) < 0) - Py_FatalError("Py_InitializeMainInterpreter: unable to load the file system codec"); + err = initfsencoding(interp); + if (_Py_INIT_FAILED(err)) { + return err; + } - if (config->install_signal_handlers) - initsigs(); /* Signal handling stuff, including initintr() */ + if (config->install_signal_handlers) { + err = initsigs(); /* Signal handling stuff, including initintr() */ + if (_Py_INIT_FAILED(err)) { + return err; + } + } if (_PyTraceMalloc_Init() < 0) - Py_FatalError("Py_InitializeMainInterpreter: can't initialize tracemalloc"); + return _Py_INIT_ERR("can't initialize tracemalloc"); - initmain(interp); /* Module __main__ */ - if (initstdio() < 0) - Py_FatalError( - "Py_InitializeMainInterpreter: can't initialize sys standard streams"); + err = add_main_module(interp); + if (_Py_INIT_FAILED(err)) { + return err; + } + if (initstdio() < 0) { + return _Py_INIT_ERR("can't initialize sys standard streams"); + } /* Initialize warnings. */ if (PySys_HasWarnOptions()) { @@ -901,37 +953,57 @@ int _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) _PyRuntime.initialized = 1; - if (!Py_NoSiteFlag) - initsite(); /* Module site */ + if (!Py_NoSiteFlag) { + err = initsite(); /* Module site */ + if (_Py_INIT_FAILED(err)) { + return err; + } + } - return 0; + return _Py_INIT_OK(); } #undef _INIT_DEBUG_PRINT -void +_PyInitError _Py_InitializeEx_Private(int install_sigs, int install_importlib) { _PyCoreConfig core_config = _PyCoreConfig_INIT; _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; + _PyInitError err; /* TODO: Moar config options! */ core_config.ignore_environment = Py_IgnoreEnvironmentFlag; core_config._disable_importlib = !install_importlib; config.install_signal_handlers = install_sigs; - _Py_InitializeCore(&core_config); + + err = _Py_InitializeCore(&core_config); + if (_Py_INIT_FAILED(err)) { + return err; + } + /* TODO: Print any exceptions raised by these operations */ - if (_Py_ReadMainInterpreterConfig(&config)) - Py_FatalError("Py_Initialize: Py_ReadMainInterpreterConfig failed"); - if (_Py_InitializeMainInterpreter(&config)) - Py_FatalError("Py_Initialize: Py_InitializeMainInterpreter failed"); + err = _Py_ReadMainInterpreterConfig(&config); + if (_Py_INIT_FAILED(err)) { + return err; + } + + err = _Py_InitializeMainInterpreter(&config); + if (_Py_INIT_FAILED(err)) { + return err; + } + + return _Py_INIT_OK(); } void Py_InitializeEx(int install_sigs) { - _Py_InitializeEx_Private(install_sigs, 1); + _PyInitError err = _Py_InitializeEx_Private(install_sigs, 1); + if (_Py_INIT_FAILED(err)) { + _Py_FatalInitError(err); + } } void @@ -1236,6 +1308,7 @@ Py_NewInterpreter(void) PyInterpreterState *interp; PyThreadState *tstate, *save_tstate; PyObject *bimod, *sysmod; + _PyInitError err = _Py_INIT_OK(); if (!_PyRuntime.initialized) Py_FatalError("Py_NewInterpreter: call Py_Initialize first"); @@ -1308,25 +1381,50 @@ Py_NewInterpreter(void) PySys_SetObject("__stderr__", pstderr); Py_DECREF(pstderr); - _PyImportHooks_Init(); + err = _PyImportHooks_Init(); + if (_Py_INIT_FAILED(err)) { + goto init_failed; + } - initimport(interp, sysmod); - initexternalimport(interp); + err = initimport(interp, sysmod); + if (_Py_INIT_FAILED(err)) { + goto init_failed; + } - if (initfsencoding(interp) < 0) - goto handle_error; + err = initexternalimport(interp); + if (_Py_INIT_FAILED(err)) { + goto init_failed; + } - if (initstdio() < 0) - Py_FatalError( - "Py_NewInterpreter: can't initialize sys standard streams"); - initmain(interp); - if (!Py_NoSiteFlag) - initsite(); + err = initfsencoding(interp); + if (_Py_INIT_FAILED(err)) { + goto init_failed; + } + + if (initstdio() < 0) { + err = _Py_INIT_ERR("can't initialize sys standard streams"); + goto init_failed; + } + + err = add_main_module(interp); + if (_Py_INIT_FAILED(err)) { + goto init_failed; + } + + if (!Py_NoSiteFlag) { + err = initsite(); + if (_Py_INIT_FAILED(err)) { + goto init_failed; + } + } } if (!PyErr_Occurred()) return tstate; +init_failed: + _Py_FatalInitError(err); + handle_error: /* Oops, it didn't work. Undo it all. */ @@ -1417,32 +1515,35 @@ Py_GetPythonHome(void) return home; } -/* Create __main__ module */ +/* Add the __main__ module */ -static void -initmain(PyInterpreterState *interp) +static _PyInitError +add_main_module(PyInterpreterState *interp) { PyObject *m, *d, *loader, *ann_dict; m = PyImport_AddModule("__main__"); if (m == NULL) - Py_FatalError("can't create __main__ module"); + return _Py_INIT_ERR("can't create __main__ module"); + d = PyModule_GetDict(m); ann_dict = PyDict_New(); if ((ann_dict == NULL) || (PyDict_SetItemString(d, "__annotations__", ann_dict) < 0)) { - Py_FatalError("Failed to initialize __main__.__annotations__"); + return _Py_INIT_ERR("Failed to initialize __main__.__annotations__"); } Py_DECREF(ann_dict); + if (PyDict_GetItemString(d, "__builtins__") == NULL) { PyObject *bimod = PyImport_ImportModule("builtins"); if (bimod == NULL) { - Py_FatalError("Failed to retrieve builtins module"); + return _Py_INIT_ERR("Failed to retrieve builtins module"); } if (PyDict_SetItemString(d, "__builtins__", bimod) < 0) { - Py_FatalError("Failed to initialize __main__.__builtins__"); + return _Py_INIT_ERR("Failed to initialize __main__.__builtins__"); } Py_DECREF(bimod); } + /* Main is a little special - imp.is_builtin("__main__") will return * False, but BuiltinImporter is still the most appropriate initial * setting for its __loader__ attribute. A more suitable value will @@ -1454,41 +1555,40 @@ initmain(PyInterpreterState *interp) PyObject *loader = PyObject_GetAttrString(interp->importlib, "BuiltinImporter"); if (loader == NULL) { - Py_FatalError("Failed to retrieve BuiltinImporter"); + return _Py_INIT_ERR("Failed to retrieve BuiltinImporter"); } if (PyDict_SetItemString(d, "__loader__", loader) < 0) { - Py_FatalError("Failed to initialize __main__.__loader__"); + return _Py_INIT_ERR("Failed to initialize __main__.__loader__"); } Py_DECREF(loader); } + return _Py_INIT_OK(); } -static int +static _PyInitError initfsencoding(PyInterpreterState *interp) { PyObject *codec; #ifdef MS_WINDOWS - if (Py_LegacyWindowsFSEncodingFlag) - { + if (Py_LegacyWindowsFSEncodingFlag) { Py_FileSystemDefaultEncoding = "mbcs"; Py_FileSystemDefaultEncodeErrors = "replace"; } - else - { + else { Py_FileSystemDefaultEncoding = "utf-8"; Py_FileSystemDefaultEncodeErrors = "surrogatepass"; } #else - if (Py_FileSystemDefaultEncoding == NULL) - { + if (Py_FileSystemDefaultEncoding == NULL) { Py_FileSystemDefaultEncoding = get_locale_encoding(); - if (Py_FileSystemDefaultEncoding == NULL) - Py_FatalError("Py_Initialize: Unable to get the locale encoding"); + if (Py_FileSystemDefaultEncoding == NULL) { + return _Py_INIT_ERR("Unable to get the locale encoding"); + } Py_HasFileSystemDefaultEncoding = 0; interp->fscodec_initialized = 1; - return 0; + return _Py_INIT_OK(); } #endif @@ -1498,29 +1598,25 @@ initfsencoding(PyInterpreterState *interp) /* Such error can only occurs in critical situations: no more * memory, import a module of the standard library failed, * etc. */ - return -1; + return _Py_INIT_ERR("unable to load the file system codec"); } Py_DECREF(codec); interp->fscodec_initialized = 1; - return 0; + return _Py_INIT_OK(); } /* Import the site module (not into __main__ though) */ -static void +static _PyInitError initsite(void) { PyObject *m; m = PyImport_ImportModule("site"); if (m == NULL) { - fprintf(stderr, "Failed to import the site module\n"); - PyErr_Print(); - Py_Finalize(); - exit(1); - } - else { - Py_DECREF(m); + return _Py_INIT_USER_ERR("Failed to import the site module"); } + Py_DECREF(m); + return _Py_INIT_OK(); } /* Check if a file descriptor is valid or not. @@ -1926,8 +2022,8 @@ fatal_output_debug(const char *msg) } #endif -void -Py_FatalError(const char *msg) +static void +fatal_error(const char *prefix, const char *msg, int status) { const int fd = fileno(stderr); static int reentrant = 0; @@ -1939,7 +2035,18 @@ Py_FatalError(const char *msg) } reentrant = 1; - fprintf(stderr, "Fatal Python error: %s\n", msg); + fprintf(stderr, "Fatal Python error: "); + if (prefix) { + fputs(prefix, stderr); + fputs(": ", stderr); + } + if (msg) { + fputs(msg, stderr); + } + else { + fprintf(stderr, "<message not set>"); + } + fputs("\n", stderr); fflush(stderr); /* it helps in Windows debug build */ /* Print the exception (if an exception is set) with its traceback, @@ -1965,10 +2072,30 @@ Py_FatalError(const char *msg) #endif /* MS_WINDOWS */ exit: + if (status < 0) { #if defined(MS_WINDOWS) && defined(_DEBUG) - DebugBreak(); + DebugBreak(); #endif - abort(); + abort(); + } + else { + exit(status); + } +} + +void +Py_FatalError(const char *msg) +{ + fatal_error(NULL, msg, -1); +} + +void +_Py_FatalInitError(_PyInitError err) +{ + /* On "user" error: exit with status 1. + For all other errors, call abort(). */ + int status = err.user_err ? 1 : -1; + fatal_error(err.prefix, err.msg, status); } /* Clean up and exit */ @@ -2045,7 +2172,7 @@ Py_Exit(int sts) exit(sts); } -static void +static _PyInitError initsigs(void) { #ifdef SIGPIPE @@ -2059,8 +2186,9 @@ initsigs(void) #endif PyOS_InitInterrupts(); /* May imply initsignal() */ if (PyErr_Occurred()) { - Py_FatalError("Py_Initialize: can't import signal"); + return _Py_INIT_ERR("can't import signal"); } + return _Py_INIT_OK(); } |