Skip to content

bug: unprotected concurrent map reads in warehouse slave worker_job.go (data race) #7002

Description

@RockyOmvi

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions