Browse Source

Issue #15781: Fix two small race conditions in import's module locking.

pull/2332/head
Antoine Pitrou 14 years ago
parent
commit
0398985920
  1. 10
      Lib/importlib/_bootstrap.py
  2. 12
      Lib/test/test_threaded_import.py
  3. 2
      Misc/NEWS
  4. 6
      Python/import.c
  5. 7264
      Python/importlib.h

10
Lib/importlib/_bootstrap.py

@ -268,8 +268,10 @@ def _get_module_lock(name):
Should only be called with the import lock taken."""
lock = None
if name in _module_locks:
try:
lock = _module_locks[name]()
except KeyError:
pass
if lock is None:
if _thread is None:
lock = _DummyModuleLock(name)
@ -543,6 +545,9 @@ def module_for_loader(fxn):
# implicitly imports 'locale' and would otherwise trigger an
# infinite loop.
module = new_module(fullname)
# This must be done before putting the module in sys.modules
# (otherwise an optimization shortcut in import.c becomes wrong)
module.__initializing__ = True
sys.modules[fullname] = module
module.__loader__ = self
try:
@ -554,8 +559,9 @@ def module_for_loader(fxn):
module.__package__ = fullname
else:
module.__package__ = fullname.rpartition('.')[0]
try:
else:
module.__initializing__ = True
try:
# If __package__ was not set above, __import__() will do it later.
return fxn(self, module, *args, **kwargs)
except:

12
Lib/test/test_threaded_import.py

@ -224,7 +224,17 @@ class ThreadedImportTests(unittest.TestCase):
@reap_threads
def test_main():
run_unittest(ThreadedImportTests)
old_switchinterval = None
try:
old_switchinterval = sys.getswitchinterval()
sys.setswitchinterval(0.00000001)
except AttributeError:
pass
try:
run_unittest(ThreadedImportTests)
finally:
if old_switchinterval is not None:
sys.setswitchinterval(old_switchinterval)
if __name__ == "__main__":
test_main()

2
Misc/NEWS

@ -13,6 +13,8 @@ Core and Builtins
- Issue #15784: Modify OSError.__str__() to better distinguish between
errno error numbers and Windows error numbers.
- Issue #15781: Fix two small race conditions in import's module locking.
Library
-------

6
Python/import.c

@ -1408,7 +1408,11 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
int initializing = 0;
Py_INCREF(mod);
/* Only call _bootstrap._lock_unlock_module() if __initializing__ is true. */
/* Optimization: only call _bootstrap._lock_unlock_module() if
__initializing__ is true.
NOTE: because of this, __initializing__ must be set *before*
stuffing the new module in sys.modules.
*/
value = _PyObject_GetAttrId(mod, &PyId___initializing__);
if (value == NULL)
PyErr_Clear();

7264
Python/importlib.h
File diff suppressed because it is too large
View File

Loading…
Cancel
Save