Skip to content

Commit 80ead7c

Browse files
f41gh7hagen1778
andauthored
app/vmauth: remove readTrackingBody pool (VictoriaMetrics#8104)
Sync.Pool for readTrackingBody was added in order to reduce potential load on garbage collector. But golang net/http standard library does not allow to reuse request body, since it closes body asynchronously after return. Related issue: golang/go#51907 This commit removes sync.Pool in order to fix potential panic and data race at requests processing. Affected releases: - all releases after v1.97.7 Related issue: VictoriaMetrics#8051 Signed-off-by: f41gh7 <[email protected]> Co-authored-by: Roman Khavronenko <[email protected]>
1 parent 8772288 commit 80ead7c

File tree

3 files changed

+11
-33
lines changed

3 files changed

+11
-33
lines changed

app/vmauth/main.go

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,7 @@ func processRequest(w http.ResponseWriter, r *http.Request, ui *UserInfo) {
222222
isDefault = true
223223
}
224224

225-
rtb := getReadTrackingBody(r.Body, maxRequestBodySizeToRetry.IntN())
226-
defer putReadTrackingBody(rtb)
225+
rtb := newReadTrackingBody(r.Body, maxRequestBodySizeToRetry.IntN())
227226
r.Body = rtb
228227

229228
maxAttempts := up.getBackendsCount()
@@ -559,22 +558,11 @@ type readTrackingBody struct {
559558
bufComplete bool
560559
}
561560

562-
func (rtb *readTrackingBody) reset() {
563-
rtb.maxBodySize = 0
564-
rtb.r = nil
565-
rtb.buf = rtb.buf[:0]
566-
rtb.readBuf = nil
567-
rtb.cannotRetry = false
568-
rtb.bufComplete = false
569-
}
570-
571-
func getReadTrackingBody(r io.ReadCloser, maxBodySize int) *readTrackingBody {
572-
v := readTrackingBodyPool.Get()
573-
if v == nil {
574-
v = &readTrackingBody{}
575-
}
576-
rtb := v.(*readTrackingBody)
577-
561+
func newReadTrackingBody(r io.ReadCloser, maxBodySize int) *readTrackingBody {
562+
// do not use sync.Pool there
563+
// since http.RoundTrip may still use request body after return
564+
// See this issue for details https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8051
565+
rtb := &readTrackingBody{}
578566
if maxBodySize < 0 {
579567
maxBodySize = 0
580568
}
@@ -597,13 +585,6 @@ func (r *zeroReader) Close() error {
597585
return nil
598586
}
599587

600-
func putReadTrackingBody(rtb *readTrackingBody) {
601-
rtb.reset()
602-
readTrackingBodyPool.Put(rtb)
603-
}
604-
605-
var readTrackingBodyPool sync.Pool
606-
607588
// Read implements io.Reader interface.
608589
func (rtb *readTrackingBody) Read(p []byte) (int, error) {
609590
if len(rtb.readBuf) > 0 {

app/vmauth/main_test.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -545,8 +545,7 @@ func TestReadTrackingBody_RetrySuccess(t *testing.T) {
545545
f := func(s string, maxBodySize int) {
546546
t.Helper()
547547

548-
rtb := getReadTrackingBody(io.NopCloser(bytes.NewBufferString(s)), maxBodySize)
549-
defer putReadTrackingBody(rtb)
548+
rtb := newReadTrackingBody(io.NopCloser(bytes.NewBufferString(s)), maxBodySize)
550549

551550
if !rtb.canRetry() {
552551
t.Fatalf("canRetry() must return true before reading anything")
@@ -581,8 +580,7 @@ func TestReadTrackingBody_RetrySuccessPartialRead(t *testing.T) {
581580
t.Helper()
582581

583582
// Check the case with partial read
584-
rtb := getReadTrackingBody(io.NopCloser(bytes.NewBufferString(s)), maxBodySize)
585-
defer putReadTrackingBody(rtb)
583+
rtb := newReadTrackingBody(io.NopCloser(bytes.NewBufferString(s)), maxBodySize)
586584

587585
for i := 0; i < len(s); i++ {
588586
buf := make([]byte, i)
@@ -631,8 +629,7 @@ func TestReadTrackingBody_RetryFailureTooBigBody(t *testing.T) {
631629
f := func(s string, maxBodySize int) {
632630
t.Helper()
633631

634-
rtb := getReadTrackingBody(io.NopCloser(bytes.NewBufferString(s)), maxBodySize)
635-
defer putReadTrackingBody(rtb)
632+
rtb := newReadTrackingBody(io.NopCloser(bytes.NewBufferString(s)), maxBodySize)
636633

637634
if !rtb.canRetry() {
638635
t.Fatalf("canRetry() must return true before reading anything")
@@ -681,8 +678,7 @@ func TestReadTrackingBody_RetryFailureZeroOrNegativeMaxBodySize(t *testing.T) {
681678
f := func(s string, maxBodySize int) {
682679
t.Helper()
683680

684-
rtb := getReadTrackingBody(io.NopCloser(bytes.NewBufferString(s)), maxBodySize)
685-
defer putReadTrackingBody(rtb)
681+
rtb := newReadTrackingBody(io.NopCloser(bytes.NewBufferString(s)), maxBodySize)
686682

687683
if !rtb.canRetry() {
688684
t.Fatalf("canRetry() must return true before reading anything")

docs/changelog/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ See also [LTS releases](https://docs.victoriametrics.com/lts-releases/).
2525

2626
* BUGFIX: [vmsingle](https://docs.victoriametrics.com/single-server-victoriametrics/), `vminsert` in [VictoriaMetrics cluster](https://docs.victoriametrics.com/cluster-victoriametrics/) and [vmagent](https://docs.victoriametrics.com/vmagent/): allow ingesting histograms with missing `_sum` metric via [OpenTelemetry ingestion protocol](https://docs.victoriametrics.com/#sending-data-via-opentelemetry) in the same way as Prometheus does.
2727
* BUGFIX: all VictoriaMetrics [enterprise](https://docs.victoriametrics.com/enterprise/) components: properly trim whitespaces at the end of license provided via `-license` and `-licenseFile` command-line flags. Previously, the trailing whitespaces could cause the license verification to fail.
28+
* BUGFIX: [vmauth](https://docs.victoriametrics.com/vmauth/): fix possible runtime panic during requests processing under heavy load. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/8051) for details.
2829

2930
## [v1.109.1](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.109.1)
3031

0 commit comments

Comments
 (0)