| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent af3c1d8 commit fe993a0
1 file changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1185,19 +1185,51 @@ is_core_module(PyInterpreterState *interp, PyObject *name, PyObject *path) | |||
| 1185 | 1185 | return 0; | |
| 1186 | 1186 | } | |
| 1187 | 1187 | ||
| 1188 | + #ifndef NDEBUG | ||
| 1189 | + static bool | ||
| 1190 | + is_singlephase(PyModuleDef *def) | ||
| 1191 | + { | ||
| 1192 | + if (def == NULL) { | ||
| 1193 | + /* It must be a module created by reload_singlephase_extension() | ||
| 1194 | + * from m_copy. Ideally we'd do away with this case. */ | ||
| 1195 | + return true; | ||
| 1196 | + } | ||
| 1197 | + else if (def->m_slots == NULL) { | ||
| 1198 | + return true; | ||
| 1199 | + } | ||
| 1200 | + else { | ||
| 1201 | + return false; | ||
| 1202 | + } | ||
| 1203 | + } | ||
| 1204 | + #endif | ||
| 1205 | + | ||
| 1206 | + | ||
| 1207 | + struct singlephase_global_update { | ||
| 1208 | + PyObject *m_dict; | ||
| 1209 | + }; | ||
| 1188 | 1210 | ||
| 1189 | 1211 | static int | |
| 1190 | 1212 | update_global_state_for_extension(PyThreadState *tstate, | |
| 1191 | - PyObject *mod, PyModuleDef *def, | ||
| 1192 | - PyObject *name, PyObject *path) | ||
| 1213 | + PyObject *path, PyObject *name, | ||
| 1214 | + PyModuleDef *def, | ||
| 1215 | + struct singlephase_global_update *singlephase) | ||
| 1193 | 1216 | { | |
| 1194 | - assert(mod != NULL && PyModule_Check(mod)); | ||
| 1195 | - assert(def == _PyModule_GetDef(mod)); | ||
| 1196 | - | ||
| 1197 | - // bpo-44050: Extensions and def->m_base.m_copy can be updated | ||
| 1198 | - // when the extension module doesn't support sub-interpreters. | ||
| 1199 | - if (def->m_size == -1) { | ||
| 1200 | - if (!is_core_module(tstate->interp, name, path)) { | ||
| 1217 | + /* Copy the module's __dict__, if applicable. */ | ||
| 1218 | + if (singlephase == NULL) { | ||
| 1219 | + assert(def->m_base.m_copy == NULL); | ||
| 1220 | + } | ||
| 1221 | + else { | ||
| 1222 | + assert(def->m_base.m_init != NULL | ||
| 1223 | + || is_core_module(tstate->interp, name, path)); | ||
| 1224 | + if (singlephase->m_dict == NULL) { | ||
| 1225 | + assert(def->m_base.m_copy == NULL); | ||
| 1226 | + } | ||
| 1227 | + else { | ||
| 1228 | + assert(PyDict_Check(singlephase->m_dict)); | ||
| 1229 | + // gh-88216: Extensions and def->m_base.m_copy can be updated | ||
| 1230 | + // when the extension module doesn't support sub-interpreters. | ||
| 1231 | + assert(def->m_size == -1); | ||
| 1232 | + assert(!is_core_module(tstate->interp, name, path)); | ||
| 1201 | 1233 | assert(PyUnicode_CompareWithASCIIString(name, "sys") != 0); | |
| 1202 | 1234 | assert(PyUnicode_CompareWithASCIIString(name, "builtins") != 0); | |
| 1203 | 1235 | if (def->m_base.m_copy) { | |
@@ -1206,17 +1238,16 @@ update_global_state_for_extension(PyThreadState *tstate, | |||
| 1206 | 1238 | XXX this should really not happen. */ | |
| 1207 | 1239 | Py_CLEAR(def->m_base.m_copy); | |
| 1208 | 1240 | } | |
| 1209 | - PyObject *dict = PyModule_GetDict(mod); | ||
| 1210 | - if (dict == NULL) { | ||
| 1211 | - return -1; | ||
| 1212 | - } | ||
| 1213 | - def->m_base.m_copy = PyDict_Copy(dict); | ||
| 1241 | + def->m_base.m_copy = PyDict_Copy(singlephase->m_dict); | ||
| 1214 | 1242 | if (def->m_base.m_copy == NULL) { | |
| 1243 | + // XXX Ignore this error? Doing so would effectively | ||
| 1244 | + // mark the module as not loadable. */ | ||
| 1215 | 1245 | return -1; | |
| 1216 | 1246 | } | |
| 1217 | 1247 | } | |
| 1218 | 1248 | } | |
| 1219 | 1249 | ||
| 1250 | + /* Add the module's def to the global cache. */ | ||
| 1220 | 1251 | // XXX Why special-case the main interpreter? | |
| 1221 | 1252 | if (_Py_IsMainInterpreter(tstate->interp) || def->m_size == -1) { | |
| 1222 | 1253 | #ifndef NDEBUG | |
@@ -1258,6 +1289,8 @@ int | |||
| 1258 | 1289 | _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name, | |
| 1259 | 1290 | PyObject *filename, PyObject *modules) | |
| 1260 | 1291 | { | |
| 1292 | + PyThreadState *tstate = _PyThreadState_GET(); | ||
| 1293 | + | ||
| 1261 | 1294 | if (mod == NULL || !PyModule_Check(mod)) { | |
| 1262 | 1295 | PyErr_BadInternalCall(); | |
| 1263 | 1296 | return -1; | |
@@ -1268,15 +1301,28 @@ _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name, | |||
| 1268 | 1301 | return -1; | |
| 1269 | 1302 | } | |
| 1270 | 1303 | ||
| 1271 | - PyThreadState *tstate = _PyThreadState_GET(); | ||
| 1304 | + /* Only single-phase init extension modules can reach here. */ | ||
| 1305 | + assert(is_singlephase(def)); | ||
| 1306 | + assert(!is_core_module(tstate->interp, name, filename)); | ||
| 1307 | + assert(!is_core_module(tstate->interp, name, name)); | ||
| 1308 | + | ||
| 1309 | + struct singlephase_global_update singlephase = {0}; | ||
| 1310 | + // gh-88216: Extensions and def->m_base.m_copy can be updated | ||
| 1311 | + // when the extension module doesn't support sub-interpreters. | ||
| 1312 | + if (def->m_size == -1) { | ||
| 1313 | + singlephase.m_dict = PyModule_GetDict(mod); | ||
| 1314 | + assert(singlephase.m_dict != NULL); | ||
| 1315 | + } | ||
| 1272 | 1316 | if (update_global_state_for_extension( | |
| 1273 | - tstate, mod, def, name, filename) < 0) | ||
| 1317 | + tstate, filename, name, def, &singlephase) < 0) | ||
| 1274 | 1318 | { | |
| 1275 | 1319 | return -1; | |
| 1276 | 1320 | } | |
| 1321 | + | ||
| 1277 | 1322 | if (finish_singlephase_extension(tstate, mod, def, name, modules) < 0) { | |
| 1278 | 1323 | return -1; | |
| 1279 | 1324 | } | |
| 1325 | + | ||
| 1280 | 1326 | return 0; | |
| 1281 | 1327 | } | |
| 1282 | 1328 | ||
@@ -1407,11 +1453,25 @@ _PyImport_FixupBuiltin(PyThreadState *tstate, PyObject *mod, const char *name, | |||
| 1407 | 1453 | goto finally; | |
| 1408 | 1454 | } | |
| 1409 | 1455 | ||
| 1456 | + /* We only use _PyImport_FixupBuiltin() for the core builtin modules | ||
| 1457 | + * (sys and builtins). These modules are single-phase init with no | ||
| 1458 | + * module state, but we also don't populate def->m_base.m_copy | ||
| 1459 | + * for them. */ | ||
| 1460 | + assert(is_core_module(tstate->interp, nameobj, nameobj)); | ||
| 1461 | + assert(is_singlephase(def)); | ||
| 1462 | + assert(def->m_size == -1); | ||
| 1463 | + assert(def->m_base.m_copy == NULL); | ||
| 1464 | + | ||
| 1465 | + struct singlephase_global_update singlephase = { | ||
| 1466 | + /* We don't want def->m_base.m_copy populated. */ | ||
| 1467 | + .m_dict=NULL, | ||
| 1468 | + }; | ||
| 1410 | 1469 | if (update_global_state_for_extension( | |
| 1411 | - tstate, mod, def, nameobj, nameobj) < 0) | ||
| 1470 | + tstate, nameobj, nameobj, def, &singlephase) < 0) | ||
| 1412 | 1471 | { | |
| 1413 | 1472 | goto finally; | |
| 1414 | 1473 | } | |
| 1474 | + | ||
| 1415 | 1475 | if (finish_singlephase_extension(tstate, mod, def, nameobj, modules) < 0) { | |
| 1416 | 1476 | goto finally; | |
| 1417 | 1477 | } | |
@@ -1444,6 +1504,7 @@ is_builtin(PyObject *name) | |||
| 1444 | 1504 | static PyObject* | |
| 1445 | 1505 | create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec) | |
| 1446 | 1506 | { | |
| 1507 | + PyModuleDef *def = NULL; | ||
| 1447 | 1508 | PyObject *mod = import_find_extension(tstate, name, name); | |
| 1448 | 1509 | if (mod || _PyErr_Occurred(tstate)) { | |
| 1449 | 1510 | return mod; | |
@@ -1473,20 +1534,32 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec) | |||
| 1473 | 1534 | } | |
| 1474 | 1535 | ||
| 1475 | 1536 | if (PyObject_TypeCheck(mod, &PyModuleDef_Type)) { | |
| 1476 | - return PyModule_FromDefAndSpec((PyModuleDef*)mod, spec); | ||
| 1537 | + def = (PyModuleDef*)mod; | ||
| 1538 | + assert(!is_singlephase(def)); | ||
| 1539 | + return PyModule_FromDefAndSpec(def, spec); | ||
| 1477 | 1540 | } | |
| 1478 | 1541 | else { | |
| 1479 | 1542 | assert(PyModule_Check(mod)); | |
| 1480 | - PyModuleDef *def = PyModule_GetDef(mod); | ||
| 1543 | + def = PyModule_GetDef(mod); | ||
| 1481 | 1544 | if (def == NULL) { | |
| 1482 | 1545 | return NULL; | |
| 1483 | 1546 | } | |
| 1547 | + assert(is_singlephase(def)); | ||
| 1484 | 1548 | ||
| 1485 | 1549 | /* Remember pointer to module init function. */ | |
| 1486 | 1550 | def->m_base.m_init = p0; | |
| 1487 | 1551 | ||
| 1552 | + struct singlephase_global_update singlephase = {0}; | ||
| 1553 | + // gh-88216: Extensions and def->m_base.m_copy can be updated | ||
| 1554 | + // when the extension module doesn't support sub-interpreters. | ||
| 1555 | + if (def->m_size == -1 | ||
| 1556 | + && !is_core_module(tstate->interp, name, name)) | ||
| 1557 | + { | ||
| 1558 | + singlephase.m_dict = PyModule_GetDict(mod); | ||
| 1559 | + assert(singlephase.m_dict != NULL); | ||
| 1560 | + } | ||
| 1488 | 1561 | if (update_global_state_for_extension( | |
| 1489 | - tstate, mod, def, name, name) < 0) | ||
| 1562 | + tstate, name, name, def, &singlephase) < 0) | ||
| 1490 | 1563 | { | |
| 1491 | 1564 | return NULL; | |
| 1492 | 1565 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments