From b2fb51be1f9a284f907803fd5c48ee17f697f4ba Mon Sep 17 00:00:00 2001 From: Seebs Date: Wed, 26 Jun 2019 16:11:44 -0500 Subject: [PATCH] view.deleteFragment should hold the lock while altering fragments If you delete a fragment while something else is calling allFragments, you can cause a race. This almost never happens in practice, because deleting fragments is rare, and the only likely overlap would be with something like the holder cache flush, which only happens once a minute. But if you slowed down the rest of the tests enough, and ran with -race, you might see it. We check v.fragments directly instead of calling v.Fragment, because v.Fragment also needs a lock, and we don't want to drop the lock between the check for existence and the delete operation. --- view.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/view.go b/view.go index 5aba4dbd3..85c9ebbba 100644 --- a/view.go +++ b/view.go @@ -278,7 +278,9 @@ func (v *view) newFragment(path string, shard uint64) *fragment { // deleteFragment removes the fragment from the view. func (v *view) deleteFragment(shard uint64) error { - fragment := v.Fragment(shard) + v.mu.Lock() + defer v.mu.Unlock() + fragment := v.fragments[shard] if fragment == nil { return ErrFragmentNotFound }