Skip to content

Commit 3421a19

Browse files
Pass the interpreter config to init_interpreter().
1 parent 7aa33a9 commit 3421a19

File tree

3 files changed

+89
-85
lines changed

3 files changed

+89
-85
lines changed

Include/internal/pycore_interp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ extern int _PyInterpreterState_HasFeature(PyInterpreterState *interp,
399399

400400
PyAPI_FUNC(PyStatus) _PyInterpreterState_New(
401401
PyThreadState *tstate,
402+
const PyInterpreterConfig *config,
402403
PyInterpreterState **pinterp);
403404

404405

Python/pylifecycle.c

Lines changed: 16 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -551,62 +551,6 @@ pycore_init_runtime(_PyRuntimeState *runtime,
551551
}
552552

553553

554-
static PyStatus
555-
init_interp_settings(PyInterpreterState *interp,
556-
const PyInterpreterConfig *config)
557-
{
558-
assert(interp->feature_flags == 0);
559-
560-
if (config->use_main_obmalloc) {
561-
interp->feature_flags |= Py_RTFLAGS_USE_MAIN_OBMALLOC;
562-
}
563-
else if (!config->check_multi_interp_extensions) {
564-
/* The reason: PyModuleDef.m_base.m_copy leaks objects between
565-
interpreters. */
566-
return _PyStatus_ERR("per-interpreter obmalloc does not support "
567-
"single-phase init extension modules");
568-
}
569-
#ifdef Py_GIL_DISABLED
570-
if (!_Py_IsMainInterpreter(interp) &&
571-
!config->check_multi_interp_extensions)
572-
{
573-
return _PyStatus_ERR("The free-threaded build does not support "
574-
"single-phase init extension modules in "
575-
"subinterpreters");
576-
}
577-
#endif
578-
579-
if (config->allow_fork) {
580-
interp->feature_flags |= Py_RTFLAGS_FORK;
581-
}
582-
if (config->allow_exec) {
583-
interp->feature_flags |= Py_RTFLAGS_EXEC;
584-
}
585-
// Note that fork+exec is always allowed.
586-
587-
if (config->allow_threads) {
588-
interp->feature_flags |= Py_RTFLAGS_THREADS;
589-
}
590-
if (config->allow_daemon_threads) {
591-
interp->feature_flags |= Py_RTFLAGS_DAEMON_THREADS;
592-
}
593-
594-
if (config->check_multi_interp_extensions) {
595-
interp->feature_flags |= Py_RTFLAGS_MULTI_INTERP_EXTENSIONS;
596-
}
597-
598-
switch (config->gil) {
599-
case PyInterpreterConfig_DEFAULT_GIL: break;
600-
case PyInterpreterConfig_SHARED_GIL: break;
601-
case PyInterpreterConfig_OWN_GIL: break;
602-
default:
603-
return _PyStatus_ERR("invalid interpreter config 'gil' value");
604-
}
605-
606-
return _PyStatus_OK();
607-
}
608-
609-
610554
static void
611555
init_interp_create_gil(PyThreadState *tstate, int gil)
612556
{
@@ -643,8 +587,15 @@ pycore_create_interpreter(_PyRuntimeState *runtime,
643587
PyThreadState **tstate_p)
644588
{
645589
PyStatus status;
590+
591+
PyInterpreterConfig config = _PyInterpreterConfig_LEGACY_INIT;
592+
// The main interpreter always has its own GIL and supports single-phase
593+
// init extensions.
594+
config.gil = PyInterpreterConfig_OWN_GIL;
595+
config.check_multi_interp_extensions = 0;
596+
646597
PyInterpreterState *interp;
647-
status = _PyInterpreterState_New(NULL, &interp);
598+
status = _PyInterpreterState_New(NULL, &config, &interp);
648599
if (_PyStatus_EXCEPTION(status)) {
649600
return status;
650601
}
@@ -664,16 +615,6 @@ pycore_create_interpreter(_PyRuntimeState *runtime,
664615
return status;
665616
}
666617

667-
PyInterpreterConfig config = _PyInterpreterConfig_LEGACY_INIT;
668-
// The main interpreter always has its own GIL and supports single-phase
669-
// init extensions.
670-
config.gil = PyInterpreterConfig_OWN_GIL;
671-
config.check_multi_interp_extensions = 0;
672-
status = init_interp_settings(interp, &config);
673-
if (_PyStatus_EXCEPTION(status)) {
674-
return status;
675-
}
676-
677618
// initialize the interp->obmalloc state. This must be done after
678619
// the settings are loaded (so that feature_flags are set) but before
679620
// any calls are made to obmalloc functions.
@@ -2253,18 +2194,19 @@ new_interpreter(PyThreadState **tstate_p,
22532194
interpreters: disable PyGILState_Check(). */
22542195
runtime->gilstate.check_enabled = 0;
22552196

2256-
PyInterpreterState *interp = PyInterpreterState_New();
2257-
if (interp == NULL) {
2258-
*tstate_p = NULL;
2259-
return _PyStatus_OK();
2260-
}
2261-
_PyInterpreterState_SetWhence(interp, whence);
2262-
interp->_ready = 1;
22632197

22642198
// XXX Might new_interpreter() have been called without the GIL held?
22652199
PyThreadState *save_tstate = _PyThreadState_GET();
22662200
PyThreadState *tstate = NULL;
22672201

2202+
PyInterpreterState *interp;
2203+
status = _PyInterpreterState_New(save_tstate, config, &interp);
2204+
if (_PyStatus_EXCEPTION(status)) {
2205+
return status;
2206+
}
2207+
_PyInterpreterState_SetWhence(interp, whence);
2208+
interp->_ready = 1;
2209+
22682210
/* From this point until the init_interp_create_gil() call,
22692211
we must not do anything that requires that the GIL be held
22702212
(or otherwise exist). That applies whether or not the new
@@ -2291,12 +2233,6 @@ new_interpreter(PyThreadState **tstate_p,
22912233
goto error;
22922234
}
22932235

2294-
/* This does not require that the GIL be held. */
2295-
status = init_interp_settings(interp, config);
2296-
if (_PyStatus_EXCEPTION(status)) {
2297-
goto error;
2298-
}
2299-
23002236
// initialize the interp->obmalloc state. This must be done after
23012237
// the settings are loaded (so that feature_flags are set) but before
23022238
// any calls are made to obmalloc functions.

Python/pystate.c

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -581,9 +581,66 @@ free_interpreter(PyInterpreterState *interp)
581581
PyMem_RawFree(interp);
582582
}
583583
}
584+
585+
static PyStatus
586+
init_interp_settings(PyInterpreterState *interp,
587+
const PyInterpreterConfig *config)
588+
{
589+
assert(interp->feature_flags == 0);
590+
591+
if (config->use_main_obmalloc) {
592+
interp->feature_flags |= Py_RTFLAGS_USE_MAIN_OBMALLOC;
593+
}
594+
else if (!config->check_multi_interp_extensions) {
595+
/* The reason: PyModuleDef.m_base.m_copy leaks objects between
596+
interpreters. */
597+
return _PyStatus_ERR("per-interpreter obmalloc does not support "
598+
"single-phase init extension modules");
599+
}
600+
#ifdef Py_GIL_DISABLED
601+
if (!_Py_IsMainInterpreter(interp) &&
602+
!config->check_multi_interp_extensions)
603+
{
604+
return _PyStatus_ERR("The free-threaded build does not support "
605+
"single-phase init extension modules in "
606+
"subinterpreters");
607+
}
608+
#endif
609+
610+
if (config->allow_fork) {
611+
interp->feature_flags |= Py_RTFLAGS_FORK;
612+
}
613+
if (config->allow_exec) {
614+
interp->feature_flags |= Py_RTFLAGS_EXEC;
615+
}
616+
// Note that fork+exec is always allowed.
617+
618+
if (config->allow_threads) {
619+
interp->feature_flags |= Py_RTFLAGS_THREADS;
620+
}
621+
if (config->allow_daemon_threads) {
622+
interp->feature_flags |= Py_RTFLAGS_DAEMON_THREADS;
623+
}
624+
625+
if (config->check_multi_interp_extensions) {
626+
interp->feature_flags |= Py_RTFLAGS_MULTI_INTERP_EXTENSIONS;
627+
}
628+
629+
switch (config->gil) {
630+
case PyInterpreterConfig_DEFAULT_GIL: break;
631+
case PyInterpreterConfig_SHARED_GIL: break;
632+
case PyInterpreterConfig_OWN_GIL: break;
633+
default:
634+
return _PyStatus_ERR("invalid interpreter config 'gil' value");
635+
}
636+
637+
return _PyStatus_OK();
638+
}
639+
584640
#ifndef NDEBUG
585641
static inline int check_interpreter_whence(long);
586642
#endif
643+
587644
/* Get the interpreter state to a minimal consistent state.
588645
Further init happens in pylifecycle.c before it can be used.
589646
All fields not initialized here are expected to be zeroed out,
@@ -607,7 +664,8 @@ static PyStatus
607664
init_interpreter(PyInterpreterState *interp,
608665
_PyRuntimeState *runtime, int64_t id,
609666
PyInterpreterState *next,
610-
long whence)
667+
long whence,
668+
const PyInterpreterConfig *config)
611669
{
612670
if (interp->_initialized) {
613671
return _PyStatus_ERR("interpreter already initialized");
@@ -629,10 +687,15 @@ init_interpreter(PyInterpreterState *interp,
629687
assert(next != NULL || (interp == runtime->interpreters.main));
630688
interp->next = next;
631689

690+
PyStatus status = init_interp_settings(interp, config);
691+
if (_PyStatus_EXCEPTION(status)) {
692+
return status;
693+
}
694+
632695
// This relies on interp->feature_flags being set already,
633696
// but currently we don't set that by this point.
634697
// That's something to fix.
635-
PyStatus status = _PyObject_InitState(interp);
698+
status = _PyObject_InitState(interp);
636699
if (_PyStatus_EXCEPTION(status)) {
637700
return status;
638701
}
@@ -673,7 +736,9 @@ init_interpreter(PyInterpreterState *interp,
673736

674737

675738
PyStatus
676-
_PyInterpreterState_New(PyThreadState *tstate, PyInterpreterState **pinterp)
739+
_PyInterpreterState_New(PyThreadState *tstate,
740+
const PyInterpreterConfig *config,
741+
PyInterpreterState **pinterp)
677742
{
678743
*pinterp = NULL;
679744

@@ -735,7 +800,7 @@ _PyInterpreterState_New(PyThreadState *tstate, PyInterpreterState **pinterp)
735800

736801
long whence = _PyInterpreterState_WHENCE_UNKNOWN;
737802
status = init_interpreter(interp, runtime,
738-
id, old_head, whence);
803+
id, old_head, whence, config);
739804
if (_PyStatus_EXCEPTION(status)) {
740805
goto error;
741806
}
@@ -762,8 +827,10 @@ PyInterpreterState_New(void)
762827
// tstate can be NULL
763828
PyThreadState *tstate = current_fast_get();
764829

830+
const PyInterpreterConfig config = _PyInterpreterConfig_LEGACY_INIT;
831+
765832
PyInterpreterState *interp;
766-
PyStatus status = _PyInterpreterState_New(tstate, &interp);
833+
PyStatus status = _PyInterpreterState_New(tstate, &config, &interp);
767834
if (_PyStatus_EXCEPTION(status)) {
768835
Py_ExitStatusException(status);
769836
}

0 commit comments

Comments
 (0)