bpo-38091: Import deadlock detection causes deadlock (GH-17518)
Automerge-Triggered-By: @brettcannon
This commit is contained in:
parent
ce3a498408
commit
6daa37fd42
|
@ -67,6 +67,7 @@ class _ModuleLock:
|
||||||
# Deadlock avoidance for concurrent circular imports.
|
# Deadlock avoidance for concurrent circular imports.
|
||||||
me = _thread.get_ident()
|
me = _thread.get_ident()
|
||||||
tid = self.owner
|
tid = self.owner
|
||||||
|
seen = set()
|
||||||
while True:
|
while True:
|
||||||
lock = _blocking_on.get(tid)
|
lock = _blocking_on.get(tid)
|
||||||
if lock is None:
|
if lock is None:
|
||||||
|
@ -74,6 +75,14 @@ class _ModuleLock:
|
||||||
tid = lock.owner
|
tid = lock.owner
|
||||||
if tid == me:
|
if tid == me:
|
||||||
return True
|
return True
|
||||||
|
if tid in seen:
|
||||||
|
# bpo 38091: the chain of tid's we encounter here
|
||||||
|
# eventually leads to a fixpoint or a cycle, but
|
||||||
|
# does not reach 'me'. This means we would not
|
||||||
|
# actually deadlock. This can happen if other
|
||||||
|
# threads are at the beginning of acquire() below.
|
||||||
|
return False
|
||||||
|
seen.add(tid)
|
||||||
|
|
||||||
def acquire(self):
|
def acquire(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -436,16 +436,24 @@ class ImportTests(unittest.TestCase):
|
||||||
os.does_not_exist
|
os.does_not_exist
|
||||||
|
|
||||||
def test_concurrency(self):
|
def test_concurrency(self):
|
||||||
|
# bpo 38091: this is a hack to slow down the code that calls
|
||||||
|
# has_deadlock(); the logic was itself sometimes deadlocking.
|
||||||
|
def delay_has_deadlock(frame, event, arg):
|
||||||
|
if event == 'call' and frame.f_code.co_name == 'has_deadlock':
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'data'))
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'data'))
|
||||||
try:
|
try:
|
||||||
exc = None
|
exc = None
|
||||||
def run():
|
def run():
|
||||||
|
sys.settrace(delay_has_deadlock)
|
||||||
event.wait()
|
event.wait()
|
||||||
try:
|
try:
|
||||||
import package
|
import package
|
||||||
except BaseException as e:
|
except BaseException as e:
|
||||||
nonlocal exc
|
nonlocal exc
|
||||||
exc = e
|
exc = e
|
||||||
|
sys.settrace(None)
|
||||||
|
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
event = threading.Event()
|
event = threading.Event()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Tweak import deadlock detection code to not deadlock itself.
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue