Commit b8b042c5 authored by Kirill Smelkov's avatar Kirill Smelkov

sync.WorkGroup: Fix deadlock thinko in tests

sync.WorkGroup test was doing ctx.done() wait from under test mutex,
something like

    def _(ctx, i):
        with mu:
            ...
            if i == 0:
                raise RuntimeError()    # to cause ctx cancel
            ctx.done().recv()           # i=1 -> wait till ctx is canceled

but it can be a deadlock if T(i=1) runs first and enters
ctx.done().recv() before T(i=0) is run - then T(i=0) will block forever
waiting to lock mu.

This failure was not seen so far, probably because the time to go a new
thread/goroutine is relatively high. However one of upcoming patches,
where go is made faster, revealed this problem and, without the fix,
sync.WorkGroup test was regularly deadlocking.

The problem was there from sync.WorkGroup beginning - from
9ee7ba91 (sync += WorkGroup).

Fix the deadlock by waiting for ctx.done() outside of mu.
parent 086d4296
...@@ -146,9 +146,9 @@ def test_workgroup(): ...@@ -146,9 +146,9 @@ def test_workgroup():
l[i] = i+1 l[i] = i+1
if i == 0: if i == 0:
raise MyError('bbb') raise MyError('bbb')
if i == 1: if i == 1:
ctx.done().recv() ctx.done().recv()
raise ValueError('ccc') # != MyError raise ValueError('ccc') # != MyError
def f(ctx, i): def f(ctx, i):
Iam_f = 0 Iam_f = 0
_(ctx, i) _(ctx, i)
...@@ -171,7 +171,7 @@ def test_workgroup(): ...@@ -171,7 +171,7 @@ def test_workgroup():
def _(ctx, i): def _(ctx, i):
with mu: with mu:
l[i] = i+1 l[i] = i+1
ctx.done().recv() ctx.done().recv()
wg.go(_, i) wg.go(_, i)
cancel() # parent cancel - must be propagated into workgroup cancel() # parent cancel - must be propagated into workgroup
wg.wait() wg.wait()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment