@@ -69,6 +69,7 @@ extern void _PyFaulthandler_Fini(void);
6969extern void _PyHash_Fini (void );
7070extern int _PyTraceMalloc_Init (void );
7171extern int _PyTraceMalloc_Fini (void );
72+ extern void _Py_ReadyTypes (void );
7273
7374#ifdef WITH_THREAD
7475extern void _PyGILState_Init (PyInterpreterState * , PyThreadState * );
@@ -112,6 +113,7 @@ PyModule_GetWarningsModule(void)
112113 return PyImport_ImportModule ("warnings" );
113114}
114115
116+
115117/* APIs to access the initialization flags
116118 *
117119 * Can be called prior to Py_Initialize.
@@ -366,8 +368,8 @@ void _Py_InitializeCore(const _PyCoreConfig *config)
366368 PyThreadState * tstate ;
367369 PyObject * bimod , * sysmod , * pstderr ;
368370 char * p ;
369- extern void _Py_ReadyTypes (void );
370371 _PyCoreConfig core_config = _PyCoreConfig_INIT ;
372+ _PyMainInterpreterConfig preinit_config = _PyMainInterpreterConfig_INIT ;
371373
372374 if (config != NULL ) {
373375 core_config = * config ;
@@ -428,6 +430,7 @@ void _Py_InitializeCore(const _PyCoreConfig *config)
428430 if (interp == NULL )
429431 Py_FatalError ("Py_InitializeCore: can't make main interpreter" );
430432 interp -> core_config = core_config ;
433+ interp -> config = preinit_config ;
431434
432435 tstate = PyThreadState_New (interp );
433436 if (tstate == NULL )
@@ -518,21 +521,62 @@ void _Py_InitializeCore(const _PyCoreConfig *config)
518521 _Py_CoreInitialized = 1 ;
519522}
520523
521- int
522- _Py_InitializeMainInterpreter (int install_sigs )
524+ /* Read configuration settings from standard locations
525+ *
526+ * This function doesn't make any changes to the interpreter state - it
527+ * merely populates any missing configuration settings. This allows an
528+ * embedding application to completely override a config option by
529+ * setting it before calling this function, or else modify the default
530+ * setting before passing the fully populated config to Py_EndInitialization.
531+ *
532+ * More advanced selective initialization tricks are possible by calling
533+ * this function multiple times with various preconfigured settings.
534+ */
535+
536+ int _Py_ReadMainInterpreterConfig (_PyMainInterpreterConfig * config )
537+ {
538+ /* Signal handlers are installed by default */
539+ if (config -> install_signal_handlers < 0 ) {
540+ config -> install_signal_handlers = 1 ;
541+ }
542+
543+ return 0 ;
544+ }
545+
546+ /* Update interpreter state based on supplied configuration settings
547+ *
548+ * After calling this function, most of the restrictions on the interpreter
549+ * are lifted. The only remaining incomplete settings are those related
550+ * to the main module (sys.argv[0], __main__ metadata)
551+ *
552+ * Calling this when the interpreter is not initializing, is already
553+ * initialized or without a valid current thread state is a fatal error.
554+ * Other errors should be reported as normal Python exceptions with a
555+ * non-zero return code.
556+ */
557+ int _Py_InitializeMainInterpreter (const _PyMainInterpreterConfig * config )
523558{
524559 PyInterpreterState * interp ;
525560 PyThreadState * tstate ;
526561
562+ if (!_Py_CoreInitialized ) {
563+ Py_FatalError ("Py_InitializeMainInterpreter: runtime core not initialized" );
564+ }
565+ if (_Py_Initialized ) {
566+ Py_FatalError ("Py_InitializeMainInterpreter: main interpreter already initialized" );
567+ }
568+
527569 /* Get current thread state and interpreter pointer */
528570 tstate = PyThreadState_GET ();
529571 if (!tstate )
530- Py_FatalError ("Py_Initialize : failed to read thread state" );
572+ Py_FatalError ("Py_InitializeMainInterpreter : failed to read thread state" );
531573 interp = tstate -> interp ;
532574 if (!interp )
533- Py_FatalError ("Py_Initialize : failed to get interpreter" );
575+ Py_FatalError ("Py_InitializeMainInterpreter : failed to get interpreter" );
534576
535577 /* Now finish configuring the main interpreter */
578+ interp -> config = * config ;
579+
536580 if (interp -> core_config ._disable_importlib ) {
537581 /* Special mode for freeze_importlib: run with no import system
538582 *
@@ -545,7 +589,7 @@ _Py_InitializeMainInterpreter(int install_sigs)
545589 /* TODO: Report exceptions rather than fatal errors below here */
546590
547591 if (_PyTime_Init () < 0 )
548- Py_FatalError ("Py_Initialize : can't initialize time" );
592+ Py_FatalError ("Py_InitializeMainInterpreter : can't initialize time" );
549593
550594 /* Finish setting up the sys module and import system */
551595 /* GetPath may initialize state that _PySys_EndInit locks
@@ -559,21 +603,21 @@ _Py_InitializeMainInterpreter(int install_sigs)
559603
560604 /* initialize the faulthandler module */
561605 if (_PyFaulthandler_Init ())
562- Py_FatalError ("Py_Initialize : can't initialize faulthandler" );
606+ Py_FatalError ("Py_InitializeMainInterpreter : can't initialize faulthandler" );
563607
564608 if (initfsencoding (interp ) < 0 )
565- Py_FatalError ("Py_Initialize : unable to load the file system codec" );
609+ Py_FatalError ("Py_InitializeMainInterpreter : unable to load the file system codec" );
566610
567- if (install_sigs )
611+ if (config -> install_signal_handlers )
568612 initsigs (); /* Signal handling stuff, including initintr() */
569613
570614 if (_PyTraceMalloc_Init () < 0 )
571- Py_FatalError ("Py_Initialize : can't initialize tracemalloc" );
615+ Py_FatalError ("Py_InitializeMainInterpreter : can't initialize tracemalloc" );
572616
573617 initmain (interp ); /* Module __main__ */
574618 if (initstdio () < 0 )
575619 Py_FatalError (
576- "Py_Initialize : can't initialize sys standard streams" );
620+ "Py_InitializeMainInterpreter : can't initialize sys standard streams" );
577621
578622 /* Initialize warnings. */
579623 if (PySys_HasWarnOptions ()) {
@@ -590,19 +634,27 @@ _Py_InitializeMainInterpreter(int install_sigs)
590634 if (!Py_NoSiteFlag )
591635 initsite (); /* Module site */
592636
593- return 0 ;
637+ return 0 ;
594638}
595639
640+ #undef _INIT_DEBUG_PRINT
641+
596642void
597643_Py_InitializeEx_Private (int install_sigs , int install_importlib )
598644{
599645 _PyCoreConfig core_config = _PyCoreConfig_INIT ;
646+ _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT ;
600647
601648 /* TODO: Moar config options! */
602649 core_config .ignore_environment = Py_IgnoreEnvironmentFlag ;
603650 core_config ._disable_importlib = !install_importlib ;
651+ config .install_signal_handlers = install_sigs ;
604652 _Py_InitializeCore (& core_config );
605- _Py_InitializeMainInterpreter (install_sigs );
653+ /* TODO: Print any exceptions raised by these operations */
654+ if (_Py_ReadMainInterpreterConfig (& config ))
655+ Py_FatalError ("Py_Initialize: Py_ReadMainInterpreterConfig failed" );
656+ if (_Py_InitializeMainInterpreter (& config ))
657+ Py_FatalError ("Py_Initialize: Py_InitializeMainInterpreter failed" );
606658}
607659
608660
@@ -932,10 +984,12 @@ Py_NewInterpreter(void)
932984 /* Copy the current interpreter config into the new interpreter */
933985 if (save_tstate != NULL ) {
934986 interp -> core_config = save_tstate -> interp -> core_config ;
987+ interp -> config = save_tstate -> interp -> config ;
935988 } else {
936989 /* No current thread state, copy from the main interpreter */
937990 PyInterpreterState * main_interp = PyInterpreterState_Main ();
938991 interp -> core_config = main_interp -> core_config ;
992+ interp -> config = main_interp -> config ;
939993 }
940994
941995 /* XXX The following is lax in error checking */
0 commit comments