Skip to content

Commit a0aefcf

Browse files
acudzelig
authored andcommitted
storage: fix pyramid chunker and hasherstore possible deadlocks (ethersphere#1679)
* storage: prevent deadlock on hasherstore * storage: pyramid chunker quit only once
1 parent bec590a commit a0aefcf

File tree

2 files changed

+18
-5
lines changed

2 files changed

+18
-5
lines changed

storage/hasherstore.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,10 @@ func (h *hasherStore) startWait(ctx context.Context) {
152152
select {
153153
// if context is done earlier, just return with the error
154154
case <-ctx.Done():
155-
h.waitC <- ctx.Err()
155+
select {
156+
case h.waitC <- ctx.Err():
157+
case <-h.quitC:
158+
}
156159
return
157160
// doneC is closed if all chunks have been submitted, from then we just wait until all of them are also stored
158161
case <-doneC:
@@ -161,7 +164,10 @@ func (h *hasherStore) startWait(ctx context.Context) {
161164
// a chunk has been stored, if err is nil, then successfully, so increase the stored chunk counter
162165
case err := <-h.errC:
163166
if err != nil {
164-
h.waitC <- err
167+
select {
168+
case h.waitC <- err:
169+
case <-h.quitC:
170+
}
165171
return
166172
}
167173
nrStoredChunks++

storage/pyramid.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ type PyramidChunker struct {
149149
wg *sync.WaitGroup
150150
errC chan error
151151
quitC chan bool
152+
quitOnce sync.Once
152153
rootAddress []byte
153154
chunkLevel [][]*TreeEntry
154155
}
@@ -218,7 +219,7 @@ func (pc *PyramidChunker) Split(ctx context.Context) (k Address, wait func(conte
218219
close(pc.errC)
219220
}()
220221

221-
defer close(pc.quitC)
222+
defer pc.quit()
222223
defer pc.putter.Close()
223224

224225
select {
@@ -250,7 +251,7 @@ func (pc *PyramidChunker) Append(ctx context.Context) (k Address, wait func(cont
250251
close(pc.errC)
251252
}()
252253

253-
defer close(pc.quitC)
254+
defer pc.quit()
254255
defer pc.putter.Close()
255256

256257
select {
@@ -469,7 +470,7 @@ func (pc *PyramidChunker) prepareChunks(ctx context.Context, isAppend bool) {
469470
break
470471
}
471472
} else {
472-
close(pc.quitC)
473+
pc.quit()
473474
break
474475
}
475476
}
@@ -704,3 +705,9 @@ func (pc *PyramidChunker) cleanChunkLevels() {
704705
}
705706
}
706707
}
708+
709+
func (pc *PyramidChunker) quit() {
710+
pc.quitOnce.Do(func() {
711+
close(pc.quitC)
712+
})
713+
}

0 commit comments

Comments
 (0)