Describe the bug
In warehouse/slave/worker_job.go, the uploadLoadFiles method reads jr.outputFileWritersMap and jr.tableEventCountMap from both the main goroutine and a spawned upload goroutine without holding their respective mutexes (outputFileWritersMapMu / tableEventCountMapMu).
This is a data race detectable by the Go race detector.
Code reference
warehouse/slave/worker_job.go:415 (main goroutine — no lock):
processStream := make(chan *uploadProcessingResult, len(jr.outputFileWritersMap))
warehouse/slave/worker_job.go:420-450 (upload goroutine — no lock):
go func() {
for tableName, uploadFile := range jr.outputFileWritersMap {
// ...
TotalRows: jr.tableEventCountMap[tableName],
}
}()
warehouse/slave/worker_job.go:473 (main goroutine — no lock):
output := make([]uploadResult, 0, len(jr.outputFileWritersMap))
warehouse/slave/worker_job.go:483 (main goroutine — no lock):
if len(output) != len(jr.outputFileWritersMap) { ... }
Steps to reproduce
Run the warehouse tests with the -race flag:
go test -race ./warehouse/slave/...
Expected behavior
All reads of outputFileWritersMap and tableEventCountMap should be protected by outputFileWritersMapMu.RLock() / tableEventCountMapMu.RLock():
jr.outputFileWritersMapMu.RLock()
defer jr.outputFileWritersMapMu.RUnlock()
for tableName, uploadFile := range jr.outputFileWritersMap { ... }
Additional context
The uploadLoadFiles function is called from processStagingFile (line 499) after a call to uploadLoadFiles on the previous line. The maps are populated in handlePendingStagingFile which holds the write locks. While in practice uploadLoadFiles may be called after all map population is complete, there is no formal synchronization guarantee, and the Go race detector correctly flags these as unsynchronized concurrent reads.
Describe the bug
In
warehouse/slave/worker_job.go, theuploadLoadFilesmethod readsjr.outputFileWritersMapandjr.tableEventCountMapfrom both the main goroutine and a spawned upload goroutine without holding their respective mutexes (outputFileWritersMapMu/tableEventCountMapMu).This is a data race detectable by the Go race detector.
Code reference
warehouse/slave/worker_job.go:415(main goroutine — no lock):warehouse/slave/worker_job.go:420-450(upload goroutine — no lock):warehouse/slave/worker_job.go:473(main goroutine — no lock):warehouse/slave/worker_job.go:483(main goroutine — no lock):Steps to reproduce
Run the warehouse tests with the
-raceflag:Expected behavior
All reads of
outputFileWritersMapandtableEventCountMapshould be protected byoutputFileWritersMapMu.RLock()/tableEventCountMapMu.RLock():Additional context
The
uploadLoadFilesfunction is called fromprocessStagingFile(line 499) after a call touploadLoadFileson the previous line. The maps are populated inhandlePendingStagingFilewhich holds the write locks. While in practiceuploadLoadFilesmay be called after all map population is complete, there is no formal synchronization guarantee, and the Go race detector correctly flags these as unsynchronized concurrent reads.