Open LeeTeng2001 opened 1 day ago
An alternative solution is to modify Descendants
to consume everything without processing
func Descendants(ctx context.Context, getLinks dag.GetLinks, set *cid.Set, roots <-chan pin.StreamedPin) error {
// ...
for {
select {
case <-ctx.Done():
for range roots {}
return ctx.Err()
case wrapper, ok := <-roots:
// ...
}
}
}
Checklist
Installation method
built from source
Version
Config
Description
I noticed a deadlock caused by GC, after debugging for a while, I found the problematic part and have a solution for it. To reproduce, download a file with ipfs, next, run a GC with cancelled context, download a new file with ipfs, the file will hang at 100% while waiting for pinner to pin the file.
The issue occurs at race condition at GC.
GC will invoke
ColoredSet
which in turns invoke pinnerRecursiveKeys
to get a channel. The channel will passed into Descendants to iterate result.The race condition lies between the interaction between pinner's
streamIndex
andDescendants
When the passed in context is cancelled, pinner's streamIndex goroutine will immediately return an error which it wants to deliver outside via the unbuffered
out
channel. At theDescendants
side, the channel will never be read because the select statement contains theout
channel and context, when the context is cancelled, it'll immediately return without ever reading theout
channel.My proposed solution is simple, change the streamIndex channel to a buffered channel
Though, I'm not sure if this will affect other part of infrastructure, please verify my solution validness. Thanks!