Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4f0338c

Browse files
committed
Issue #15781: Fix two small race conditions in import's module locking.
1 parent 79dbded commit 4f0338c

5 files changed

Lines changed: 3659 additions & 3635 deletions

File tree

Lib/importlib/_bootstrap.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,10 @@ def _get_module_lock(name):
268268
269269
Should only be called with the import lock taken."""
270270
lock = None
271-
if name in _module_locks:
271+
try:
272272
lock = _module_locks[name]()
273+
except KeyError:
274+
pass
273275
if lock is None:
274276
if _thread is None:
275277
lock = _DummyModuleLock(name)
@@ -543,6 +545,9 @@ def module_for_loader_wrapper(self, fullname, *args, **kwargs):
543545
# implicitly imports 'locale' and would otherwise trigger an
544546
# infinite loop.
545547
module = new_module(fullname)
548+
# This must be done before putting the module in sys.modules
549+
# (otherwise an optimization shortcut in import.c becomes wrong)
550+
module.__initializing__ = True
546551
sys.modules[fullname] = module
547552
module.__loader__ = self
548553
try:
@@ -554,8 +559,9 @@ def module_for_loader_wrapper(self, fullname, *args, **kwargs):
554559
module.__package__ = fullname
555560
else:
556561
module.__package__ = fullname.rpartition('.')[0]
557-
try:
562+
else:
558563
module.__initializing__ = True
564+
try:
559565
# If __package__ was not set above, __import__() will do it later.
560566
return fxn(self, module, *args, **kwargs)
561567
except:

Lib/test/test_threaded_import.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,17 @@ def target():
224224

225225
@reap_threads
226226
def test_main():
227-
run_unittest(ThreadedImportTests)
227+
old_switchinterval = None
228+
try:
229+
old_switchinterval = sys.getswitchinterval()
230+
sys.setswitchinterval(0.00000001)
231+
except AttributeError:
232+
pass
233+
try:
234+
run_unittest(ThreadedImportTests)
235+
finally:
236+
if old_switchinterval is not None:
237+
sys.setswitchinterval(old_switchinterval)
228238

229239
if __name__ == "__main__":
230240
test_main()

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ What's New in Python 3.3.0 Release Candidate 2?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #15781: Fix two small race conditions in import's module locking.
14+
1315
Library
1416
-------
1517

Python/import.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1408,7 +1408,11 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
14081408
int initializing = 0;
14091409

14101410
Py_INCREF(mod);
1411-
/* Only call _bootstrap._lock_unlock_module() if __initializing__ is true. */
1411+
/* Optimization: only call _bootstrap._lock_unlock_module() if
1412+
__initializing__ is true.
1413+
NOTE: because of this, __initializing__ must be set *before*
1414+
stuffing the new module in sys.modules.
1415+
*/
14121416
value = _PyObject_GetAttrId(mod, &PyId___initializing__);
14131417
if (value == NULL)
14141418
PyErr_Clear();

0 commit comments

Comments
 (0)