Skip to content

RTECO-1263 - Fixed Content Reader race panic#3502

Merged
fluxxBot merged 1 commit into
masterfrom
RTECO-1263-readerPanic
May 21, 2026
Merged

RTECO-1263 - Fixed Content Reader race panic#3502
fluxxBot merged 1 commit into
masterfrom
RTECO-1263-readerPanic

Conversation

@fluxxBot
Copy link
Copy Markdown
Contributor

@fluxxBot fluxxBot commented May 21, 2026

  • All tests have passed. If this feature is not already covered by the tests, new tests have been added.
  • The pull request is targeting the master branch.
  • The code has been validated to compile successfully by running go vet ./....
  • The code has been formatted properly using go fmt ./....

Summary

Fixes panic: send on closed channel in ContentReader triggered intermittently by concurrent use of NextRecord and Reset (or by callers that invoke Reset internally, e.g.
Length, SortContentReader).

Resolves RTECO-1263.

Background

ContentReader.NextRecord spawns a producer goroutine once (via sync.Once) that streams JSON array elements from one or more files into cr.dataChannel. The receiver in
NextRecord and the producer in readSingleFile both read cr.dataChannel from the struct field on each access.

Reset() replaces both cr.dataChannel and cr.once without any synchronization. This created three independent race conditions that together produce the panic:

  1. Producer / Reset race — a producer goroutine paused between sends (between files, or while blocked on a full buffer) could resume after Reset() had swapped the channel
    field. The producer's next send would land on the new channel, which could already have been closed by the next cycle's defer close.
  2. Receiver / Reset raceNextRecord could fire once.Do against the old once, then read cr.dataChannel after Reset() had swapped both fields, causing the receiver
    and producer to operate on different channels (deadlock).
  3. Defer / send mismatchdefer close(cr.dataChannel) evaluates the channel argument at defer-registration time, but cr.dataChannel <- item re-reads the field on every
    send. The defer and the send could refer to two different channels.

The race is timing-dependent; it surfaces in CI under load (e.g. TestPushFatManifestImageWithNestedPath in the docker test suite) but is hard to reproduce locally without -race
and concurrent stress.

Stack trace from the failing CI run:

panic: send on closed channel
goroutine 2699 [running]:
github.com/jfrog/jfrog-client-go/utils/io/content.(*ContentReader).readSingleFile
.../utils/io/content/contentreader.go:216 +0x492
github.com/jfrog/jfrog-client-go/utils/io/content.(*ContentReader).run(...)
.../utils/io/content/contentreader.go:178
github.com/jfrog/jfrog-client-go/utils/io/content.(*ContentReader).NextRecord.func1.1()
.../utils/io/content/contentreader.go:78 +0x7a

@fluxxBot fluxxBot added the safe to test Approve running integration tests on a pull request label May 21, 2026
@fluxxBot fluxxBot marked this pull request as ready for review May 21, 2026 12:07
@fluxxBot fluxxBot force-pushed the RTECO-1263-readerPanic branch from ff1257b to 7b5a0d8 Compare May 21, 2026 12:08
@fluxxBot fluxxBot added safe to test Approve running integration tests on a pull request and removed safe to test Approve running integration tests on a pull request labels May 21, 2026
@fluxxBot fluxxBot added bug Something isn't working safe to test Approve running integration tests on a pull request and removed safe to test Approve running integration tests on a pull request labels May 21, 2026
@fluxxBot fluxxBot enabled auto-merge (squash) May 21, 2026 12:10
@fluxxBot fluxxBot merged commit 94b7f93 into master May 21, 2026
113 of 242 checks passed
@fluxxBot fluxxBot deleted the RTECO-1263-readerPanic branch May 21, 2026 12:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working safe to test Approve running integration tests on a pull request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants