Skip to content

app/vmauth: fix data race when retrying requests on failed backends (#11508) - #11552

Closed
justonemorenight wants to merge 1 commit into
VictoriaMetrics:masterfrom
justonemorenight:fix-vmauth-data-race-11508
Closed

justonemorenight wants to merge 1 commit into
VictoriaMetrics:masterfrom
justonemorenight:fix-vmauth-data-race-11508

Conversation

@justonemorenight

Copy link
Copy Markdown

Summary

Fixes #11508

When an upstream backend returns an error or a retryable status code (such as 503) early before consuming the request body, net/http's transport background writeLoop may still be writing or closing the request body when RoundTrip returns.

Previously, req.Body and r.Body shared the same *bufferedBody instance without synchronization. When RoundTrip returned early:

  1. httpserver.GetRequestURI(r) called r.ParseForm(), which read r.Body (bb.Read()).
  2. tryProcessingRequest called bb.resetReader().
  3. Subsequent retries sent the same bb to another backend.
    Meanwhile, the first backend's writeLoop concurrently called bb.Close() (and was potentially still reading bb), causing a data race detected by Go's race detector.

Solution

  1. When canRetry is true (the entire request body was buffered into bb.buf), provide an isolated io.NopCloser(bytes.NewReader(bb.buf)) for each backend request attempt as well as for r.Body. This ensures concurrent reads/closes across attempts and GetRequestURI(r) never race on shared reader offsets.
  2. When canRetry is false (unbuffered streaming request body), set r.Body = http.NoBody after handing it off to RoundTrip, since unbuffered streams cannot be retried or re-read by GetRequestURI.
  3. Add sync.Mutex to bufferedBody for safe access to bufOffset, cannotRetry, and r.
  4. Add regression test TestBufferedBody_DataRace verifying race-free behavior under concurrent writes and early 503 responses for both retryable and unbuffered payloads.
  5. Update CHANGELOG.md.

Testing

  • go test -race ./app/vmauth/... passed cleanly without any data races.
  • go vet ./app/vmauth/... passed.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

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.

All reported issues were addressed across 3 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread app/vmauth/main.go Resolved
Comment thread app/vmauth/main_test.go Resolved
@justonemorenight
justonemorenight force-pushed the fix-vmauth-data-race-11508 branch from 97a11a1 to dc6035b Compare September 11, 2026 13:10
@f41gh7 f41gh7 self-assigned this Sep 11, 2026
@f41gh7
f41gh7 requested review from Haleygo and f41gh7 September 11, 2026 15:53
…ictoriaMetrics#11508)

When a backend returns an error or a retryable status code (such as 503) early before consuming the request body, net/http's transport background writeLoop may still be writing or closing the request body when RoundTrip returns.

Previously, req.Body and r.Body shared the same *bufferedBody instance without synchronization, causing a data race between net/http's Body.Close() and httpserver.GetRequestURI(r) / resetReader() / subsequent retries.

This commit fixes the data race by:
1. Providing an isolated bytes.Reader for each backend request attempt and for r.Body when canRetry is true.
2. Setting r.Body to http.NoBody when canRetry is false, since unbuffered streaming bodies cannot be retried or re-read by GetRequestURI.
3. Adding sync.Mutex to bufferedBody for safe concurrent access.
4. Adding regression test TestBufferedBody_DataRace verifying race-free behavior under concurrent writes and early 503 responses.
@justonemorenight
justonemorenight force-pushed the fix-vmauth-data-race-11508 branch from dc6035b to 11f3f9e Compare September 18, 2026 03:08
@makasim

makasim commented Sep 24, 2026

Copy link
Copy Markdown
Member

@justonemorenight, thank you for your effort, but this time we'd like to address the issue ourselves.

@makasim makasim closed this Sep 24, 2026
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.

Data race in vmauth

3 participants