gc: fix a potential deadlock
Events: 1. User triggers a GC. 2. User aborts the GC. 3. We fail to delete a block when the output channel is already full. This is really unlikely to happen in practice but it's still incorrect. Could be related to #6107 License: MIT Signed-off-by: Steven Allen <steven@stebalien.com>
Steven Allen committed
Mar 20, 2019 at 19:10 UTC
6f4fc6ac31fed8242aea27931bb4d3bc452d39d6
1 file changed
+6
-3
pin/gc/gc.go
+6
-3
@@ -83,7 +83,7 @@ func GC(ctx context.Context, bs bstore.GCBlockstore, dstor dstore.Datastore, pn
83
var removed uint64
84
85
loop:
86
- for {
86
+ for ctx.Err() == nil { // select may not notice that we're "done".
87
select {
88
case k, ok := <-keychan:
89
if !ok {
@@ -94,8 +94,11 @@ func GC(ctx context.Context, bs bstore.GCBlockstore, dstor dstore.Datastore, pn
94
removed++
95
if err != nil {
96
errors = true
97
- output <- Result{Error: &CannotDeleteBlockError{k, err}}
98
- //log.Errorf("Error removing key from blockstore: %s", err)
97
+ select {
98
+ case output <- Result{Error: &CannotDeleteBlockError{k, err}}:
99
+ case <-ctx.Done():
100
+ break loop
101
+ }
102
// continue as error is non-fatal
103
continue loop
104
}