Skip to content

Commit 0771928

Browse files
vstinnershihai1991
authored andcommitted
bpo-38858: _PyImport_FixupExtensionObject() handles subinterpreters (pythonGH-17350)
If _PyImport_FixupExtensionObject() is called from a subinterpreter, leave extensions unchanged and don't copy the module dictionary into def->m_base.m_copy.
1 parent 5283e57 commit 0771928

File tree

4 files changed

+70
-46
lines changed

4 files changed

+70
-46
lines changed

Include/cpython/pystate.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ struct _ts {
147147
The caller must hold the GIL.*/
148148
PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_Get(void);
149149

150-
PyAPI_FUNC(int) _PyState_AddModule(PyObject*, struct PyModuleDef*);
151150
PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *);
152151

153152
/* Similar to PyThreadState_Get(), but don't issue a fatal error

Include/internal/pycore_pystate.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,12 @@ extern void _PyInterpreterState_ClearModules(PyInterpreterState *interp);
324324

325325
PyAPI_FUNC(void) _PyGILState_Reinit(_PyRuntimeState *runtime);
326326

327+
328+
PyAPI_FUNC(int) _PyState_AddModule(
329+
PyThreadState *tstate,
330+
PyObject* module,
331+
struct PyModuleDef* def);
332+
327333
#ifdef __cplusplus
328334
}
329335
#endif

Python/import.c

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -695,50 +695,62 @@ int
695695
_PyImport_FixupExtensionObject(PyObject *mod, PyObject *name,
696696
PyObject *filename, PyObject *modules)
697697
{
698-
PyObject *dict, *key;
699-
struct PyModuleDef *def;
700-
int res;
701-
if (extensions == NULL) {
702-
extensions = PyDict_New();
703-
if (extensions == NULL)
704-
return -1;
705-
}
706698
if (mod == NULL || !PyModule_Check(mod)) {
707699
PyErr_BadInternalCall();
708700
return -1;
709701
}
710-
def = PyModule_GetDef(mod);
702+
703+
struct PyModuleDef *def = PyModule_GetDef(mod);
711704
if (!def) {
712705
PyErr_BadInternalCall();
713706
return -1;
714707
}
715-
if (PyObject_SetItem(modules, name, mod) < 0)
708+
709+
PyThreadState *tstate = _PyThreadState_GET();
710+
if (PyObject_SetItem(modules, name, mod) < 0) {
716711
return -1;
717-
if (_PyState_AddModule(mod, def) < 0) {
712+
}
713+
if (_PyState_AddModule(tstate, mod, def) < 0) {
718714
PyMapping_DelItem(modules, name);
719715
return -1;
720716
}
721-
if (def->m_size == -1) {
722-
if (def->m_base.m_copy) {
723-
/* Somebody already imported the module,
724-
likely under a different name.
725-
XXX this should really not happen. */
726-
Py_CLEAR(def->m_base.m_copy);
717+
718+
if (_Py_IsMainInterpreter(tstate)) {
719+
if (def->m_size == -1) {
720+
if (def->m_base.m_copy) {
721+
/* Somebody already imported the module,
722+
likely under a different name.
723+
XXX this should really not happen. */
724+
Py_CLEAR(def->m_base.m_copy);
725+
}
726+
PyObject *dict = PyModule_GetDict(mod);
727+
if (dict == NULL) {
728+
return -1;
729+
}
730+
def->m_base.m_copy = PyDict_Copy(dict);
731+
if (def->m_base.m_copy == NULL) {
732+
return -1;
733+
}
727734
}
728-
dict = PyModule_GetDict(mod);
729-
if (dict == NULL)
735+
736+
if (extensions == NULL) {
737+
extensions = PyDict_New();
738+
if (extensions == NULL) {
739+
return -1;
740+
}
741+
}
742+
743+
PyObject *key = PyTuple_Pack(2, filename, name);
744+
if (key == NULL) {
730745
return -1;
731-
def->m_base.m_copy = PyDict_Copy(dict);
732-
if (def->m_base.m_copy == NULL)
746+
}
747+
int res = PyDict_SetItem(extensions, key, (PyObject *)def);
748+
Py_DECREF(key);
749+
if (res < 0) {
733750
return -1;
751+
}
734752
}
735-
key = PyTuple_Pack(2, filename, name);
736-
if (key == NULL)
737-
return -1;
738-
res = PyDict_SetItem(extensions, key, (PyObject *)def);
739-
Py_DECREF(key);
740-
if (res < 0)
741-
return -1;
753+
742754
return 0;
743755
}
744756

@@ -801,7 +813,7 @@ import_find_extension(PyThreadState *tstate, PyObject *name,
801813
}
802814
Py_DECREF(mod);
803815
}
804-
if (_PyState_AddModule(mod, def) < 0) {
816+
if (_PyState_AddModule(tstate, mod, def) < 0) {
805817
PyMapping_DelItem(modules, name);
806818
return NULL;
807819
}

Python/pystate.c

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -661,9 +661,8 @@ PyState_FindModule(struct PyModuleDef* module)
661661
}
662662

663663
int
664-
_PyState_AddModule(PyObject* module, struct PyModuleDef* def)
664+
_PyState_AddModule(PyThreadState *tstate, PyObject* module, struct PyModuleDef* def)
665665
{
666-
PyInterpreterState *state;
667666
if (!def) {
668667
assert(PyErr_Occurred());
669668
return -1;
@@ -673,37 +672,45 @@ _PyState_AddModule(PyObject* module, struct PyModuleDef* def)
673672
"PyState_AddModule called on module with slots");
674673
return -1;
675674
}
676-
state = _PyInterpreterState_GET_UNSAFE();
677-
if (!state->modules_by_index) {
678-
state->modules_by_index = PyList_New(0);
679-
if (!state->modules_by_index)
675+
676+
PyInterpreterState *interp = tstate->interp;
677+
if (!interp->modules_by_index) {
678+
interp->modules_by_index = PyList_New(0);
679+
if (!interp->modules_by_index) {
680680
return -1;
681+
}
681682
}
682-
while (PyList_GET_SIZE(state->modules_by_index) <= def->m_base.m_index)
683-
if (PyList_Append(state->modules_by_index, Py_None) < 0)
683+
684+
while (PyList_GET_SIZE(interp->modules_by_index) <= def->m_base.m_index) {
685+
if (PyList_Append(interp->modules_by_index, Py_None) < 0) {
684686
return -1;
687+
}
688+
}
689+
685690
Py_INCREF(module);
686-
return PyList_SetItem(state->modules_by_index,
691+
return PyList_SetItem(interp->modules_by_index,
687692
def->m_base.m_index, module);
688693
}
689694

690695
int
691696
PyState_AddModule(PyObject* module, struct PyModuleDef* def)
692697
{
693-
Py_ssize_t index;
694-
PyInterpreterState *state = _PyInterpreterState_GET_UNSAFE();
695698
if (!def) {
696699
Py_FatalError("PyState_AddModule: Module Definition is NULL");
697700
return -1;
698701
}
699-
index = def->m_base.m_index;
700-
if (state->modules_by_index &&
701-
index < PyList_GET_SIZE(state->modules_by_index) &&
702-
module == PyList_GET_ITEM(state->modules_by_index, index)) {
702+
703+
PyThreadState *tstate = _PyThreadState_GET();
704+
PyInterpreterState *interp = tstate->interp;
705+
Py_ssize_t index = def->m_base.m_index;
706+
if (interp->modules_by_index &&
707+
index < PyList_GET_SIZE(interp->modules_by_index) &&
708+
module == PyList_GET_ITEM(interp->modules_by_index, index))
709+
{
703710
Py_FatalError("PyState_AddModule: Module already added!");
704711
return -1;
705712
}
706-
return _PyState_AddModule(module, def);
713+
return _PyState_AddModule(tstate, module, def);
707714
}
708715

709716
int

0 commit comments

Comments
 (0)