From 3481048431f48f72269651e5711f24406f4be307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Sat, 12 Oct 2019 01:13:07 +0200 Subject: [PATCH] fix events deadlock when chaining calls --- chain/events/events_height.go | 3 ++ chain/events/events_test.go | 68 +++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/chain/events/events_height.go b/chain/events/events_height.go index 0458cc4de..eded0d0c2 100644 --- a/chain/events/events_height.go +++ b/chain/events/events_height.go @@ -132,9 +132,12 @@ func (e *heightEvents) ChainAt(hnd HeightHandler, rev RevertHandler, confidence log.Warnf("events.ChainAt: calling HandleFunc with nil tipset, not found in cache: %s", err) } + e.lk.Unlock() if err := hnd(ts, bestH); err != nil { return err } + e.lk.Lock() + bestH = e.tsc.best().Height() } if bestH >= h+uint64(confidence)+e.gcConfidence { diff --git a/chain/events/events_test.go b/chain/events/events_test.go index 7706d8f47..a74417f0e 100644 --- a/chain/events/events_test.go +++ b/chain/events/events_test.go @@ -364,6 +364,74 @@ func TestAtStartConfidence(t *testing.T) { require.Equal(t, false, reverted) } +func TestAtChained(t *testing.T) { + fcs := &fakeCS{ + t: t, + h: 1, + tsc: newTSCache(2*build.ForkLengthThreshold, nil), + } + require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid))) + + events := NewEvents(context.Background(), fcs) + + var applied bool + var reverted bool + + err := events.ChainAt(func(ts *types.TipSet, curH uint64) error { + return events.ChainAt(func(ts *types.TipSet, curH uint64) error { + require.Equal(t, 10, int(ts.Height())) + applied = true + return nil + }, func(ts *types.TipSet) error { + reverted = true + return nil + }, 3, 10) + }, func(ts *types.TipSet) error { + reverted = true + return nil + }, 3, 5) + require.NoError(t, err) + + fcs.advance(0, 15, nil) + + require.Equal(t, true, applied) + require.Equal(t, false, reverted) +} + +func TestAtChainedConfidence(t *testing.T) { + fcs := &fakeCS{ + t: t, + h: 1, + tsc: newTSCache(2*build.ForkLengthThreshold, nil), + } + require.NoError(t, fcs.tsc.add(makeTs(t, 1, dummyCid))) + + events := NewEvents(context.Background(), fcs) + + fcs.advance(0, 15, nil) + + var applied bool + var reverted bool + + err := events.ChainAt(func(ts *types.TipSet, curH uint64) error { + return events.ChainAt(func(ts *types.TipSet, curH uint64) error { + require.Equal(t, 10, int(ts.Height())) + applied = true + return nil + }, func(ts *types.TipSet) error { + reverted = true + return nil + }, 3, 10) + }, func(ts *types.TipSet) error { + reverted = true + return nil + }, 3, 5) + require.NoError(t, err) + + require.Equal(t, true, applied) + require.Equal(t, false, reverted) +} + func TestCalled(t *testing.T) { fcs := &fakeCS{ t: t,