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)
This commit is contained in:
Victor Stinner 2017-11-15 15:48:08 -08:00 committed by GitHub
parent 43605e6bfa
commit f7e5b56c37
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 1346 additions and 657 deletions

View file

@ -8,7 +8,7 @@ extern "C" {
#endif
#ifndef Py_LIMITED_API
PyAPI_FUNC(void) _PyImportZip_Init(void);
PyAPI_FUNC(_PyInitError) _PyImportZip_Init(void);
PyMODINIT_FUNC PyInit_imp(void);
#endif /* !Py_LIMITED_API */

View file

@ -74,10 +74,16 @@ typedef struct pyruntimestate {
// XXX Consolidate globals found via the check-c-globals script.
} _PyRuntimeState;
#define _PyRuntimeState_INIT {.initialized = 0, .core_initialized = 0}
PyAPI_DATA(_PyRuntimeState) _PyRuntime;
PyAPI_FUNC(void) _PyRuntimeState_Init(_PyRuntimeState *);
PyAPI_FUNC(_PyInitError) _PyRuntimeState_Init(_PyRuntimeState *);
PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *);
/* Initialize _PyRuntimeState.
Return NULL on success, or return an error message on failure. */
PyAPI_FUNC(_PyInitError) _PyRuntime_Initialize(void);
#define _Py_CURRENTLY_FINALIZING(tstate) \
(_PyRuntime.finalizing == tstate)

View file

@ -20,18 +20,44 @@ PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void);
PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding,
const char *errors);
typedef struct {
const char *prefix;
const char *msg;
int user_err;
} _PyInitError;
/* Almost all errors causing Python initialization to fail */
#ifdef _MSC_VER
/* Visual Studio 2015 doesn't implement C99 __func__ in C */
# define _Py_INIT_GET_FUNC() __FUNCTION__
#else
# define _Py_INIT_GET_FUNC() __func__
#endif
#define _Py_INIT_OK() \
(_PyInitError){.prefix = NULL, .msg = NULL, .user_err = 0}
#define _Py_INIT_ERR(MSG) \
(_PyInitError){.prefix = _Py_INIT_GET_FUNC(), .msg = (MSG), .user_err = 0}
/* 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}
#define _Py_INIT_FAILED(err) \
(err.msg != NULL)
/* PEP 432 Multi-phase initialization API (Private while provisional!) */
PyAPI_FUNC(void) _Py_InitializeCore(const _PyCoreConfig *);
PyAPI_FUNC(_PyInitError) _Py_InitializeCore(const _PyCoreConfig *);
PyAPI_FUNC(int) _Py_IsCoreInitialized(void);
PyAPI_FUNC(int) _Py_ReadMainInterpreterConfig(_PyMainInterpreterConfig *);
PyAPI_FUNC(int) _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *);
PyAPI_FUNC(_PyInitError) _Py_ReadMainInterpreterConfig(_PyMainInterpreterConfig *);
PyAPI_FUNC(_PyInitError) _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *);
#endif
/* Initialization and finalization */
PyAPI_FUNC(void) Py_Initialize(void);
PyAPI_FUNC(void) Py_InitializeEx(int);
#ifndef Py_LIMITED_API
PyAPI_FUNC(void) _Py_InitializeEx_Private(int, int);
PyAPI_FUNC(_PyInitError) _Py_InitializeEx_Private(int, int);
PyAPI_FUNC(void) _Py_FatalInitError(_PyInitError err) _Py_NO_RETURN;
#endif
PyAPI_FUNC(void) Py_Finalize(void);
PyAPI_FUNC(int) Py_FinalizeEx(void);
@ -50,7 +76,7 @@ PyAPI_FUNC(void) _Py_PyAtExit(void (*func)(void));
#endif
PyAPI_FUNC(int) Py_AtExit(void (*func)(void));
PyAPI_FUNC(void) Py_Exit(int);
PyAPI_FUNC(void) Py_Exit(int) _Py_NO_RETURN;
/* Restore signals that the interpreter has called SIG_IGN on to SIG_DFL. */
#ifndef Py_LIMITED_API
@ -86,15 +112,15 @@ PyAPI_FUNC(const char *) _Py_gitversion(void);
/* Internal -- various one-time initializations */
#ifndef Py_LIMITED_API
PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void);
PyAPI_FUNC(PyObject *) _PySys_BeginInit(void);
PyAPI_FUNC(_PyInitError) _PySys_BeginInit(PyObject **sysmod);
PyAPI_FUNC(int) _PySys_EndInit(PyObject *sysdict);
PyAPI_FUNC(void) _PyImport_Init(void);
PyAPI_FUNC(_PyInitError) _PyImport_Init(void);
PyAPI_FUNC(void) _PyExc_Init(PyObject * bltinmod);
PyAPI_FUNC(void) _PyImportHooks_Init(void);
PyAPI_FUNC(_PyInitError) _PyImportHooks_Init(void);
PyAPI_FUNC(int) _PyFrame_Init(void);
PyAPI_FUNC(int) _PyFloat_Init(void);
PyAPI_FUNC(int) PyByteArray_Init(void);
PyAPI_FUNC(void) _Py_HashRandomization_Init(_PyCoreConfig *core_config);
PyAPI_FUNC(_PyInitError) _Py_HashRandomization_Init(_PyCoreConfig *core_config);
#endif
/* Various internal finalizers */

View file

@ -223,6 +223,10 @@ PyAPI_FUNC(void) PyMem_SetAllocator(PyMemAllocatorDomain domain,
PyAPI_FUNC(void) PyMem_SetupDebugHooks(void);
#endif
#ifdef Py_BUILD_CORE
PyAPI_FUNC(void) _PyMem_GetDefaultRawAllocator(PyMemAllocatorEx *alloc);
#endif
#ifdef __cplusplus
}
#endif

View file

@ -37,6 +37,11 @@ PyAPI_FUNC(PyObject *) PySys_GetXOptions(void);
PyAPI_FUNC(size_t) _PySys_GetSizeOf(PyObject *);
#endif
#ifdef Py_BUILD_CORE
PyAPI_FUNC(int) _PySys_AddXOptionWithError(const wchar_t *s);
PyAPI_FUNC(int) _PySys_AddWarnOptionWithError(PyObject *option);
#endif
#ifdef __cplusplus
}
#endif

View file

@ -1281,47 +1281,54 @@ PyInit_faulthandler(void)
return m;
}
static int
faulthandler_init_enable(void)
{
PyObject *module = PyImport_ImportModule("faulthandler");
if (module == NULL) {
return -1;
}
PyObject *res = _PyObject_CallMethodId(module, &PyId_enable, NULL);
Py_DECREF(module);
if (res == NULL) {
return -1;
}
Py_DECREF(res);
return 0;
}
/* Call faulthandler.enable() if the PYTHONFAULTHANDLER environment variable
is defined, or if sys._xoptions has a 'faulthandler' key. */
static int
faulthandler_env_options(void)
faulthandler_init_parse(void)
{
PyObject *xoptions, *key, *module, *res;
char *p;
if (!((p = Py_GETENV("PYTHONFAULTHANDLER")) && *p != '\0')) {
/* PYTHONFAULTHANDLER environment variable is missing
or an empty string */
int has_key;
xoptions = PySys_GetXOptions();
if (xoptions == NULL)
return -1;
key = PyUnicode_FromString("faulthandler");
if (key == NULL)
return -1;
has_key = PyDict_Contains(xoptions, key);
Py_DECREF(key);
if (has_key <= 0)
return has_key;
char *p = Py_GETENV("PYTHONFAULTHANDLER");
if (p && *p != '\0') {
return 1;
}
module = PyImport_ImportModule("faulthandler");
if (module == NULL) {
/* PYTHONFAULTHANDLER environment variable is missing
or an empty string */
PyObject *xoptions = PySys_GetXOptions();
if (xoptions == NULL) {
return -1;
}
res = _PyObject_CallMethodId(module, &PyId_enable, NULL);
Py_DECREF(module);
if (res == NULL)
PyObject *key = PyUnicode_FromString("faulthandler");
if (key == NULL) {
return -1;
Py_DECREF(res);
return 0;
}
int has_key = PyDict_Contains(xoptions, key);
Py_DECREF(key);
return has_key;
}
int _PyFaulthandler_Init(void)
_PyInitError
_PyFaulthandler_Init(void)
{
#ifdef HAVE_SIGALTSTACK
int err;
@ -1345,14 +1352,22 @@ int _PyFaulthandler_Init(void)
thread.cancel_event = PyThread_allocate_lock();
thread.running = PyThread_allocate_lock();
if (!thread.cancel_event || !thread.running) {
PyErr_SetString(PyExc_RuntimeError,
"could not allocate locks for faulthandler");
return -1;
return _Py_INIT_ERR("failed to allocate locks for faulthandler");
}
PyThread_acquire_lock(thread.cancel_event, 1);
#endif
return faulthandler_env_options();
int enable = faulthandler_init_parse();
if (enable < 0) {
return _Py_INIT_ERR("failed to parse faulthandler env var and cmdline");
}
if (enable) {
if (faulthandler_init_enable() < 0) {
return _Py_INIT_ERR("failed to enable faulthandler");
}
}
return _Py_INIT_OK();
}
void _PyFaulthandler_Fini(void)

File diff suppressed because it is too large Load diff

View file

@ -182,31 +182,17 @@ static struct {
#define _PyMem_Raw _PyRuntime.mem.allocators.raw
static const PyMemAllocatorEx _pymem_raw = {
#ifdef Py_DEBUG
&_PyMem_Debug.raw, PYRAWDBG_FUNCS
#else
NULL, PYRAW_FUNCS
#endif
};
#define _PyMem _PyRuntime.mem.allocators.mem
static const PyMemAllocatorEx _pymem = {
#ifdef Py_DEBUG
&_PyMem_Debug.mem, PYDBG_FUNCS
#else
NULL, PYMEM_FUNCS
#endif
};
#define _PyObject _PyRuntime.mem.allocators.obj
static const PyMemAllocatorEx _pyobject = {
#ifdef Py_DEBUG
&_PyMem_Debug.obj, PYDBG_FUNCS
#else
NULL, PYOBJ_FUNCS
#endif
};
void
_PyMem_GetDefaultRawAllocator(PyMemAllocatorEx *alloc_p)
{
PyMemAllocatorEx alloc = {NULL, PYRAW_FUNCS};
*alloc_p = alloc;
}
int
_PyMem_SetupAllocators(const char *opt)
@ -267,34 +253,52 @@ _PyMem_SetupAllocators(const char *opt)
return 0;
}
#undef PYRAW_FUNCS
#undef PYMEM_FUNCS
#undef PYOBJ_FUNCS
#undef PYRAWDBG_FUNCS
#undef PYDBG_FUNCS
static const PyObjectArenaAllocator _PyObject_Arena = {NULL,
#ifdef MS_WINDOWS
_PyObject_ArenaVirtualAlloc, _PyObject_ArenaVirtualFree
#elif defined(ARENAS_USE_MMAP)
_PyObject_ArenaMmap, _PyObject_ArenaMunmap
#else
_PyObject_ArenaMalloc, _PyObject_ArenaFree
#endif
};
void
_PyObject_Initialize(struct _pyobj_runtime_state *state)
{
PyObjectArenaAllocator _PyObject_Arena = {NULL,
#ifdef MS_WINDOWS
_PyObject_ArenaVirtualAlloc, _PyObject_ArenaVirtualFree
#elif defined(ARENAS_USE_MMAP)
_PyObject_ArenaMmap, _PyObject_ArenaMunmap
#else
_PyObject_ArenaMalloc, _PyObject_ArenaFree
#endif
};
state->allocator_arenas = _PyObject_Arena;
}
void
_PyMem_Initialize(struct _pymem_runtime_state *state)
{
state->allocators.raw = _pymem_raw;
state->allocators.mem = _pymem;
state->allocators.obj = _pyobject;
PyMemAllocatorEx pymem_raw = {
#ifdef Py_DEBUG
&_PyMem_Debug.raw, PYRAWDBG_FUNCS
#else
NULL, PYRAW_FUNCS
#endif
};
PyMemAllocatorEx pymem = {
#ifdef Py_DEBUG
&_PyMem_Debug.mem, PYDBG_FUNCS
#else
NULL, PYMEM_FUNCS
#endif
};
PyMemAllocatorEx pyobject = {
#ifdef Py_DEBUG
&_PyMem_Debug.obj, PYDBG_FUNCS
#else
NULL, PYOBJ_FUNCS
#endif
};
state->allocators.raw = pymem_raw;
state->allocators.mem = pymem;
state->allocators.obj = pyobject;
#ifdef WITH_PYMALLOC
Py_BUILD_ASSERT(NB_SMALL_SIZE_CLASSES == 64);
@ -311,6 +315,7 @@ _PyMem_Initialize(struct _pymem_runtime_state *state)
#endif /* WITH_PYMALLOC */
}
#ifdef WITH_PYMALLOC
static int
_PyMem_DebugEnabled(void)

View file

@ -57,7 +57,7 @@
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>Py_BUILD_CORE;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -113,4 +113,4 @@ $(_PGOPath)
</PropertyGroup>
<WriteLinesToFile File="$(PySourcePath)python.bat" Lines="$(_Content)" Overwrite="true" Condition="'$(_Content)' != '$(_ExistingContent)'" />
</Target>
</Project>
</Project>

View file

@ -27,13 +27,11 @@
int Py_DebugFlag;
int Py_VerboseFlag;
int Py_IgnoreEnvironmentFlag;
_PyRuntimeState _PyRuntime = {0, 0};
_PyRuntimeState _PyRuntime = _PyRuntimeState_INIT;
/* Forward */
grammar *getgrammar(const char *filename);
void Py_Exit(int) _Py_NO_RETURN;
void
Py_Exit(int sts)
{

View file

@ -81,7 +81,10 @@ main(int argc, char *argv[])
Py_SetProgramName(L"./_freeze_importlib");
/* Don't install importlib, since it could execute outdated bytecode. */
_Py_InitializeEx_Private(1, 0);
_PyInitError err = _Py_InitializeEx_Private(1, 0);
if (_Py_INIT_FAILED(err)) {
_Py_FatalInitError(err);
}
if (strstr(inpath, "_external") != NULL) {
is_bootstrap = 0;

View file

@ -1,6 +1,7 @@
/* Minimal main program -- everything is loaded from the library */
#include "Python.h"
#include "internal/pystate.h"
#include <locale.h>
#ifdef __FreeBSD__
@ -22,9 +23,16 @@ main(int argc, char **argv)
wchar_t **argv_copy;
/* We need a second copy, as Python might modify the first one. */
wchar_t **argv_copy2;
int i, res;
int i, status;
char *oldloc;
_PyInitError err = _PyRuntime_Initialize();
if (_Py_INIT_FAILED(err)) {
fprintf(stderr, "Fatal Python error: %s\n", err.msg);
fflush(stderr);
exit(1);
}
/* Force malloc() allocator to bootstrap Python */
#ifdef Py_DEBUG
(void)_PyMem_SetupAllocators("malloc_debug");
@ -88,7 +96,7 @@ main(int argc, char **argv)
setlocale(LC_ALL, oldloc);
PyMem_RawFree(oldloc);
res = Py_Main(argc, argv_copy);
status = Py_Main(argc, argv_copy);
/* Force again malloc() allocator to release memory blocks allocated
before Py_Main() */
@ -103,6 +111,6 @@ main(int argc, char **argv)
}
PyMem_RawFree(argv_copy);
PyMem_RawFree(argv_copy2);
return res;
return status;
}
#endif

View file

@ -561,15 +561,16 @@ int Py_ReadHashSeed(char *seed_text,
return 0;
}
static void
static _PyInitError
init_hash_secret(int use_hash_seed,
unsigned long hash_seed)
{
void *secret = &_Py_HashSecret;
Py_ssize_t secret_size = sizeof(_Py_HashSecret_t);
if (_Py_HashSecret_Initialized)
return;
if (_Py_HashSecret_Initialized) {
return _Py_INIT_OK();
}
_Py_HashSecret_Initialized = 1;
if (use_hash_seed) {
@ -593,12 +594,14 @@ init_hash_secret(int use_hash_seed,
pyurandom() is non-blocking mode (blocking=0): see the PEP 524. */
res = pyurandom(secret, secret_size, 0, 0);
if (res < 0) {
Py_FatalError("failed to get random numbers to initialize Python");
return _Py_INIT_ERR("failed to get random numbers "
"to initialize Python");
}
}
return _Py_INIT_OK();
}
void
_PyInitError
_Py_HashRandomization_Init(_PyCoreConfig *core_config)
{
char *seed_text;
@ -608,13 +611,13 @@ _Py_HashRandomization_Init(_PyCoreConfig *core_config)
if (use_hash_seed < 0) {
seed_text = Py_GETENV("PYTHONHASHSEED");
if (Py_ReadHashSeed(seed_text, &use_hash_seed, &hash_seed) < 0) {
Py_FatalError("PYTHONHASHSEED must be \"random\" or an integer "
"in range [0; 4294967295]");
return _Py_INIT_USER_ERR("PYTHONHASHSEED must be \"random\" "
"or an integer in range [0; 4294967295]");
}
core_config->use_hash_seed = use_hash_seed;
core_config->hash_seed = hash_seed;
}
init_hash_secret(use_hash_seed, hash_seed);
return init_hash_secret(use_hash_seed, hash_seed);
}
void

View file

@ -2,6 +2,7 @@
/* Python interpreter main program for frozen scripts */
#include "Python.h"
#include "internal/pystate.h"
#include <locale.h>
#ifdef MS_WINDOWS
@ -15,6 +16,13 @@ extern int PyInitFrozenExtensions(void);
int
Py_FrozenMain(int argc, char **argv)
{
_PyInitError err = _PyRuntime_Initialize();
if (_Py_INIT_FAILED(err)) {
fprintf(stderr, "Fatal Python error: %s\n", err.msg);
fflush(stderr);
exit(1);
}
char *p;
int i, n, sts = 1;
int inspect = 0;

View file

@ -42,19 +42,23 @@ module _imp
/* Initialize things */
void
_PyInitError
_PyImport_Init(void)
{
PyInterpreterState *interp = PyThreadState_Get()->interp;
initstr = PyUnicode_InternFromString("__init__");
if (initstr == NULL)
Py_FatalError("Can't initialize import variables");
if (initstr == NULL) {
return _Py_INIT_ERR("Can't initialize import variables");
}
interp->builtins_copy = PyDict_Copy(interp->builtins);
if (interp->builtins_copy == NULL)
Py_FatalError("Can't backup builtins dict");
if (interp->builtins_copy == NULL) {
return _Py_INIT_ERR("Can't backup builtins dict");
}
return _Py_INIT_OK();
}
void
_PyInitError
_PyImportHooks_Init(void)
{
PyObject *v, *path_hooks = NULL;
@ -80,15 +84,18 @@ _PyImportHooks_Init(void)
goto error;
err = PySys_SetObject("path_hooks", path_hooks);
if (err) {
error:
PyErr_Print();
Py_FatalError("initializing sys.meta_path, sys.path_hooks, "
"or path_importer_cache failed");
goto error;
}
Py_DECREF(path_hooks);
return _Py_INIT_OK();
error:
PyErr_Print();
return _Py_INIT_ERR("initializing sys.meta_path, sys.path_hooks, "
"or path_importer_cache failed");
}
void
_PyInitError
_PyImportZip_Init(void)
{
PyObject *path_hooks, *zimpimport;
@ -133,11 +140,11 @@ _PyImportZip_Init(void)
}
}
return;
return _Py_INIT_OK();
error:
PyErr_Print();
Py_FatalError("initializing zipimport failed");
return _Py_INIT_ERR("initializing zipimport failed");
}
/* Locking primitives to prevent parallel imports of the same module

View file

@ -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();
}

View file

@ -35,7 +35,7 @@ to avoid the expense of doing their own locking).
extern "C" {
#endif
void
_PyInitError
_PyRuntimeState_Init(_PyRuntimeState *runtime)
{
memset(runtime, 0, sizeof(*runtime));
@ -46,17 +46,19 @@ _PyRuntimeState_Init(_PyRuntimeState *runtime)
_PyEval_Initialize(&runtime->ceval);
runtime->gilstate.check_enabled = 1;
/* A TSS key must be initialized with Py_tss_NEEDS_INIT
in accordance with the specification. */
{
Py_tss_t initial = Py_tss_NEEDS_INIT;
runtime->gilstate.autoTSSkey = initial;
}
Py_tss_t initial = Py_tss_NEEDS_INIT;
runtime->gilstate.autoTSSkey = initial;
runtime->interpreters.mutex = PyThread_allocate_lock();
if (runtime->interpreters.mutex == NULL)
Py_FatalError("Can't initialize threads for interpreter");
if (runtime->interpreters.mutex == NULL) {
return _Py_INIT_ERR("Can't initialize threads for interpreter");
}
runtime->interpreters.next_id = -1;
return _Py_INIT_OK();
}
void

View file

@ -1582,13 +1582,23 @@ PySys_ResetWarnOptions(void)
PyList_SetSlice(warnoptions, 0, PyList_GET_SIZE(warnoptions), NULL);
}
void
PySys_AddWarnOptionUnicode(PyObject *unicode)
int
_PySys_AddWarnOptionWithError(PyObject *option)
{
PyObject *warnoptions = get_warnoptions();
if (warnoptions == NULL)
return;
PyList_Append(warnoptions, unicode);
if (warnoptions == NULL) {
return -1;
}
if (PyList_Append(warnoptions, option)) {
return -1;
}
return 0;
}
void
PySys_AddWarnOptionUnicode(PyObject *option)
{
(void)_PySys_AddWarnOptionWithError(option);
}
void
@ -1627,18 +1637,17 @@ get_xoptions(void)
return xoptions;
}
void
PySys_AddXOption(const wchar_t *s)
int
_PySys_AddXOptionWithError(const wchar_t *s)
{
PyObject *opts;
PyObject *name = NULL, *value = NULL;
const wchar_t *name_end;
opts = get_xoptions();
if (opts == NULL)
PyObject *opts = get_xoptions();
if (opts == NULL) {
goto error;
}
name_end = wcschr(s, L'=');
const wchar_t *name_end = wcschr(s, L'=');
if (!name_end) {
name = PyUnicode_FromWideChar(s, -1);
value = Py_True;
@ -1648,19 +1657,30 @@ PySys_AddXOption(const wchar_t *s)
name = PyUnicode_FromWideChar(s, name_end - s);
value = PyUnicode_FromWideChar(name_end + 1, -1);
}
if (name == NULL || value == NULL)
if (name == NULL || value == NULL) {
goto error;
PyDict_SetItem(opts, name, value);
}
if (PyDict_SetItem(opts, name, value) < 0) {
goto error;
}
Py_DECREF(name);
Py_DECREF(value);
return;
return 0;
error:
Py_XDECREF(name);
Py_XDECREF(value);
/* No return value, therefore clear error state if possible */
if (_PyThreadState_UncheckedGet()) {
PyErr_Clear();
return -1;
}
void
PySys_AddXOption(const wchar_t *s)
{
if (_PySys_AddXOptionWithError(s) < 0) {
/* No return value, therefore clear error state if possible */
if (_PyThreadState_UncheckedGet()) {
PyErr_Clear();
}
}
}
@ -1999,50 +2019,52 @@ static struct PyModuleDef sysmodule = {
#define SET_SYS_FROM_STRING_BORROW(key, value) \
do { \
PyObject *v = (value); \
if (v == NULL) \
return NULL; \
if (v == NULL) { \
goto err_occurred; \
} \
res = PyDict_SetItemString(sysdict, key, v); \
if (res < 0) { \
return NULL; \
goto err_occurred; \
} \
} while (0)
#define SET_SYS_FROM_STRING(key, value) \
do { \
PyObject *v = (value); \
if (v == NULL) \
return NULL; \
if (v == NULL) { \
goto err_occurred; \
} \
res = PyDict_SetItemString(sysdict, key, v); \
Py_DECREF(v); \
if (res < 0) { \
return NULL; \
goto err_occurred; \
} \
} while (0)
PyObject *
_PySys_BeginInit(void)
_PyInitError
_PySys_BeginInit(PyObject **sysmod)
{
PyObject *m, *sysdict, *version_info;
int res;
m = _PyModule_CreateInitialized(&sysmodule, PYTHON_API_VERSION);
if (m == NULL)
return NULL;
if (m == NULL) {
return _Py_INIT_ERR("failed to create a module object");
}
sysdict = PyModule_GetDict(m);
/* Check that stdin is not a directory
Using shell redirection, you can redirect stdin to a directory,
crashing the Python interpreter. Catch this common mistake here
and output a useful error message. Note that under MS Windows,
the shell already prevents that. */
#if !defined(MS_WINDOWS)
Using shell redirection, you can redirect stdin to a directory,
crashing the Python interpreter. Catch this common mistake here
and output a useful error message. Note that under MS Windows,
the shell already prevents that. */
#ifndef MS_WINDOWS
{
struct _Py_stat_struct sb;
if (_Py_fstat_noraise(fileno(stdin), &sb) == 0 &&
S_ISDIR(sb.st_mode)) {
/* There's nothing more we can do. */
/* Py_FatalError() will core dump, so just exit. */
PySys_WriteStderr("Python error: <stdin> is a directory, cannot continue\n");
exit(EXIT_FAILURE);
return _Py_INIT_USER_ERR("<stdin> is a directory, "
"cannot continue");
}
}
#endif
@ -2078,8 +2100,9 @@ _PySys_BeginInit(void)
PyLong_GetInfo());
/* initialize hash_info */
if (Hash_InfoType.tp_name == NULL) {
if (PyStructSequence_InitType2(&Hash_InfoType, &hash_info_desc) < 0)
return NULL;
if (PyStructSequence_InitType2(&Hash_InfoType, &hash_info_desc) < 0) {
goto type_init_failed;
}
}
SET_SYS_FROM_STRING("hash_info",
get_hash_info());
@ -2109,8 +2132,9 @@ _PySys_BeginInit(void)
/* version_info */
if (VersionInfoType.tp_name == NULL) {
if (PyStructSequence_InitType2(&VersionInfoType,
&version_info_desc) < 0)
return NULL;
&version_info_desc) < 0) {
goto type_init_failed;
}
}
version_info = make_version_info();
SET_SYS_FROM_STRING("version_info", version_info);
@ -2126,8 +2150,9 @@ _PySys_BeginInit(void)
/* flags */
if (FlagsType.tp_name == 0) {
if (PyStructSequence_InitType2(&FlagsType, &flags_desc) < 0)
return NULL;
if (PyStructSequence_InitType2(&FlagsType, &flags_desc) < 0) {
goto type_init_failed;
}
}
/* Set flags to their default values */
SET_SYS_FROM_STRING("flags", make_flags());
@ -2136,14 +2161,17 @@ _PySys_BeginInit(void)
/* getwindowsversion */
if (WindowsVersionType.tp_name == 0)
if (PyStructSequence_InitType2(&WindowsVersionType,
&windows_version_desc) < 0)
return NULL;
&windows_version_desc) < 0) {
goto type_init_failed;
}
/* prevent user from creating new instances */
WindowsVersionType.tp_init = NULL;
WindowsVersionType.tp_new = NULL;
assert(!PyErr_Occurred());
res = PyDict_DelItemString(WindowsVersionType.tp_dict, "__new__");
if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) {
PyErr_Clear();
}
#endif
/* float repr style: 0.03 (short) vs 0.029999999999999999 (legacy) */
@ -2161,13 +2189,22 @@ _PySys_BeginInit(void)
if (AsyncGenHooksType.tp_name == NULL) {
if (PyStructSequence_InitType2(
&AsyncGenHooksType, &asyncgen_hooks_desc) < 0) {
return NULL;
goto type_init_failed;
}
}
if (PyErr_Occurred())
return NULL;
return m;
if (PyErr_Occurred()) {
goto err_occurred;
}
*sysmod = m;
return _Py_INIT_OK();
type_init_failed:
return _Py_INIT_ERR("failed to initialize a type");
err_occurred:
return _Py_INIT_ERR("can't initialize sys module");
}
#undef SET_SYS_FROM_STRING