Skip to content

fix(joiner): resolve race condition - #5281

Closed
gacevicljubisa wants to merge 2 commits into
masterfrom
fix/joiner-race-condition
Closed

fix(joiner): resolve race condition#5281
gacevicljubisa wants to merge 2 commits into
masterfrom
fix/joiner-race-condition

Conversation

@gacevicljubisa

@gacevicljubisa gacevicljubisa commented Nov 13, 2025

Copy link
Copy Markdown
Member

Checklist

  • I have read the coding guide.
  • My change requires a documentation update, and I have done it.
  • I have added tests to cover my changes.
  • I have filled out the description and linked the related issues.

Description

Fixes a race condition in pkg/file/joiner that caused CI test timeouts. Refactored decoderCache.GetOrCreate to prevent deadlocks by correctly managing mutex locks around getter.New calls.

Makefile: Filter linker warnings and disable test caching for test-ci-race

Open API Spec Version Changes (if applicable)

Motivation and Context (Optional)

Related Issue (Optional)

Screenshots (if appropriate):

@gacevicljubisa
gacevicljubisa requested a review from janos November 13, 2025 10:51
@gacevicljubisa
gacevicljubisa marked this pull request as ready for review November 13, 2025 10:52
@gacevicljubisa
gacevicljubisa changed the base branch from feat/soc-dispersed-v3 to master November 13, 2025 10:58
Comment thread pkg/file/joiner/joiner.go
var eg errgroup.Group
j.readAtOffset(buffer, j.rootData, 0, j.span, off, 0, readLen, &bytesRead, j.rootParity, &eg)
eg, ectx := errgroup.WithContext(j.ctx)
j.readAtOffset(buffer, j.rootData, 0, j.span, off, 0, readLen, &bytesRead, j.rootParity, eg, ectx)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ectx==ctx and so therefore it is not needed to add it to the signature, since readAtOffset can just select on the struct field

Comment thread pkg/file/joiner/joiner.go
return ectx.Err()
default:
}
ch, err := g.Get(ectx, addr)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the Get method already gets passed the context, shouldn't/wouldn't it better that it just checks whether the context expired before+after doing anything? this way you get better coverage of the whole codebase instead of having to dot every usage of the method elsewhere.

Comment thread pkg/file/joiner/joiner.go
recovery := func() storage.Getter {
g.config.Logger.Debug("lazy-creating recovery decoder after fetch failed", "key", key)

if d, ok := g.getFromCache(key); ok && d != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since getter.New should return almost immediately, wouldn't it be better to just lock once and do both the get and the set, instead of locking twice, checking twice and potentially calling (and allocating) in vain to getter.New?
Bear in mind also that getter.New has side-effects as it starts a whole set of goroutines with go d.prefetch(). It would be good to avoid it if it's not necessary.

Comment thread pkg/file/joiner/joiner.go
}

key := fingerprint(addrs)
g.mu.Lock()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just my 2-cents: since one mutex lock-unlock cycle turns into multiple, the chances of having race conditions increases. Since multiple callers may have now access to the same critical section at the same time, this might cause other problems elsewhere down the line (once some of the interleaving logic changes).

@acud acud added this to the v2.8.0 milestone Feb 4, 2026
@gacevicljubisa

Copy link
Copy Markdown
Member Author

Thanks for the review! Upon testing on the current master branch, the race condition that this PR was intended to address no longer appears to be present. Closing this PR as it's no longer needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants