summaryrefslogtreecommitdiff
path: root/Python/pylifecycle.c
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2017-05-23 23:00:52 -0700
committerGitHub <noreply@github.com>2017-05-23 23:00:52 -0700
commitc7ec9985bbdbb2b073f2c37febd18268817da29a (patch)
tree4e3c90c24c8ec2aa0143949ab129d3d98258f9ef /Python/pylifecycle.c
parent9e98cd0383d9e7f06c0537038a32459bf5efa97a (diff)
downloadcpython-git-c7ec9985bbdbb2b073f2c37febd18268817da29a.tar.gz
bpo-22257: Private C-API for main interpreter initialization (PEP 432). (#1729)
(patch by Nick Coghlan)
Diffstat (limited to 'Python/pylifecycle.c')
-rw-r--r--Python/pylifecycle.c80
1 files changed, 67 insertions, 13 deletions
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index d106c45be7..fd04b8233b 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -69,6 +69,7 @@ extern void _PyFaulthandler_Fini(void);
extern void _PyHash_Fini(void);
extern int _PyTraceMalloc_Init(void);
extern int _PyTraceMalloc_Fini(void);
+extern void _Py_ReadyTypes(void);
#ifdef WITH_THREAD
extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *);
@@ -112,6 +113,7 @@ PyModule_GetWarningsModule(void)
return PyImport_ImportModule("warnings");
}
+
/* APIs to access the initialization flags
*
* Can be called prior to Py_Initialize.
@@ -366,8 +368,8 @@ void _Py_InitializeCore(const _PyCoreConfig *config)
PyThreadState *tstate;
PyObject *bimod, *sysmod, *pstderr;
char *p;
- extern void _Py_ReadyTypes(void);
_PyCoreConfig core_config = _PyCoreConfig_INIT;
+ _PyMainInterpreterConfig preinit_config = _PyMainInterpreterConfig_INIT;
if (config != NULL) {
core_config = *config;
@@ -428,6 +430,7 @@ void _Py_InitializeCore(const _PyCoreConfig *config)
if (interp == NULL)
Py_FatalError("Py_InitializeCore: can't make main interpreter");
interp->core_config = core_config;
+ interp->config = preinit_config;
tstate = PyThreadState_New(interp);
if (tstate == NULL)
@@ -518,21 +521,62 @@ void _Py_InitializeCore(const _PyCoreConfig *config)
_Py_CoreInitialized = 1;
}
-int
-_Py_InitializeMainInterpreter(int install_sigs)
+/* Read configuration settings from standard locations
+ *
+ * This function doesn't make any changes to the interpreter state - it
+ * merely populates any missing configuration settings. This allows an
+ * embedding application to completely override a config option by
+ * setting it before calling this function, or else modify the default
+ * setting before passing the fully populated config to Py_EndInitialization.
+ *
+ * More advanced selective initialization tricks are possible by calling
+ * this function multiple times with various preconfigured settings.
+ */
+
+int _Py_ReadMainInterpreterConfig(_PyMainInterpreterConfig *config)
+{
+ /* Signal handlers are installed by default */
+ if (config->install_signal_handlers < 0) {
+ config->install_signal_handlers = 1;
+ }
+
+ return 0;
+}
+
+/* Update interpreter state based on supplied configuration settings
+ *
+ * After calling this function, most of the restrictions on the interpreter
+ * are lifted. The only remaining incomplete settings are those related
+ * to the main module (sys.argv[0], __main__ metadata)
+ *
+ * Calling this when the interpreter is not initializing, is already
+ * 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.
+ */
+int _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config)
{
PyInterpreterState *interp;
PyThreadState *tstate;
+ if (!_Py_CoreInitialized) {
+ Py_FatalError("Py_InitializeMainInterpreter: runtime core not initialized");
+ }
+ if (_Py_Initialized) {
+ Py_FatalError("Py_InitializeMainInterpreter: main interpreter already initialized");
+ }
+
/* Get current thread state and interpreter pointer */
tstate = PyThreadState_GET();
if (!tstate)
- Py_FatalError("Py_Initialize: failed to read thread state");
+ Py_FatalError("Py_InitializeMainInterpreter: failed to read thread state");
interp = tstate->interp;
if (!interp)
- Py_FatalError("Py_Initialize: failed to get interpreter");
+ Py_FatalError("Py_InitializeMainInterpreter: failed to get interpreter");
/* Now finish configuring the main interpreter */
+ interp->config = *config;
+
if (interp->core_config._disable_importlib) {
/* Special mode for freeze_importlib: run with no import system
*
@@ -545,7 +589,7 @@ _Py_InitializeMainInterpreter(int install_sigs)
/* TODO: Report exceptions rather than fatal errors below here */
if (_PyTime_Init() < 0)
- Py_FatalError("Py_Initialize: can't initialize time");
+ Py_FatalError("Py_InitializeMainInterpreter: can't initialize time");
/* Finish setting up the sys module and import system */
/* GetPath may initialize state that _PySys_EndInit locks
@@ -559,21 +603,21 @@ _Py_InitializeMainInterpreter(int install_sigs)
/* initialize the faulthandler module */
if (_PyFaulthandler_Init())
- Py_FatalError("Py_Initialize: can't initialize faulthandler");
+ Py_FatalError("Py_InitializeMainInterpreter: can't initialize faulthandler");
if (initfsencoding(interp) < 0)
- Py_FatalError("Py_Initialize: unable to load the file system codec");
+ Py_FatalError("Py_InitializeMainInterpreter: unable to load the file system codec");
- if (install_sigs)
+ if (config->install_signal_handlers)
initsigs(); /* Signal handling stuff, including initintr() */
if (_PyTraceMalloc_Init() < 0)
- Py_FatalError("Py_Initialize: can't initialize tracemalloc");
+ Py_FatalError("Py_InitializeMainInterpreter: can't initialize tracemalloc");
initmain(interp); /* Module __main__ */
if (initstdio() < 0)
Py_FatalError(
- "Py_Initialize: can't initialize sys standard streams");
+ "Py_InitializeMainInterpreter: can't initialize sys standard streams");
/* Initialize warnings. */
if (PySys_HasWarnOptions()) {
@@ -590,19 +634,27 @@ _Py_InitializeMainInterpreter(int install_sigs)
if (!Py_NoSiteFlag)
initsite(); /* Module site */
- return 0;
+ return 0;
}
+#undef _INIT_DEBUG_PRINT
+
void
_Py_InitializeEx_Private(int install_sigs, int install_importlib)
{
_PyCoreConfig core_config = _PyCoreConfig_INIT;
+ _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT;
/* 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);
- _Py_InitializeMainInterpreter(install_sigs);
+ /* 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");
}
@@ -932,10 +984,12 @@ Py_NewInterpreter(void)
/* Copy the current interpreter config into the new interpreter */
if (save_tstate != NULL) {
interp->core_config = save_tstate->interp->core_config;
+ interp->config = save_tstate->interp->config;
} else {
/* No current thread state, copy from the main interpreter */
PyInterpreterState *main_interp = PyInterpreterState_Main();
interp->core_config = main_interp->core_config;
+ interp->config = main_interp->config;
}
/* XXX The following is lax in error checking */