From 428263bb6f24d7c5177f91855995fd00878235b8 Mon Sep 17 00:00:00 2001 From: Tsachi Herman <24438559+tsachiherman@users.noreply.github.com> Date: Wed, 13 Sep 2023 13:36:03 -0400 Subject: [PATCH 1/2] fix datarace. --- .../network/requestdurationlimiter.go | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/cmd/soroban-rpc/internal/network/requestdurationlimiter.go b/cmd/soroban-rpc/internal/network/requestdurationlimiter.go index fef80fd39..06929f9b9 100644 --- a/cmd/soroban-rpc/internal/network/requestdurationlimiter.go +++ b/cmd/soroban-rpc/internal/network/requestdurationlimiter.go @@ -100,24 +100,33 @@ func (w *bufferedResponseWriter) WriteOut(ctx context.Context, rw http.ResponseW for k, v := range w.header { headers[k] = v } - complete := make(chan interface{}) - go func() { - if len(w.buffer) == 0 { - if w.statusCode != 0 { - rw.WriteHeader(w.statusCode) - } - return - } + + if len(w.buffer) == 0 { if w.statusCode != 0 { rw.WriteHeader(w.statusCode) } - // the following return size/error won't help us much at this point. The request is already finalized. - rw.Write(w.buffer) //nolint:errcheck - close(complete) - }() - select { - case <-complete: - case <-ctx.Done(): + return + } + if w.statusCode != 0 { + rw.WriteHeader(w.statusCode) + } + // chunkSize defines the subset of the output buffer that we're going to attempt to write to the stream. + // we choose the typical ethernet MTU size here, to align with the expected transport layer characteristics. + const chunkSize = 1500 + // iterate on the output buffer + for startChunkIdx := 0; startChunkIdx < len(w.buffer) && ctx.Err() == nil; { + // slice the output buffer into chunks. + chunkBuf := w.buffer[startChunkIdx:] + if len(chunkBuf) > chunkSize { + chunkBuf = chunkBuf[:chunkSize] + } + // write the chunk to the stream + n, err := rw.Write(chunkBuf) + // if we weren't able to write the chunk due to an error, abort writing. + if err != nil { + break + } + startChunkIdx += n } } From 1ee2f07c9487f64235061be4342e564d514eaa03 Mon Sep 17 00:00:00 2001 From: Tsachi Herman <24438559+tsachiherman@users.noreply.github.com> Date: Wed, 13 Sep 2023 14:26:14 -0400 Subject: [PATCH 2/2] revise --- .../network/requestdurationlimiter.go | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/cmd/soroban-rpc/internal/network/requestdurationlimiter.go b/cmd/soroban-rpc/internal/network/requestdurationlimiter.go index 06929f9b9..05204591f 100644 --- a/cmd/soroban-rpc/internal/network/requestdurationlimiter.go +++ b/cmd/soroban-rpc/internal/network/requestdurationlimiter.go @@ -110,23 +110,10 @@ func (w *bufferedResponseWriter) WriteOut(ctx context.Context, rw http.ResponseW if w.statusCode != 0 { rw.WriteHeader(w.statusCode) } - // chunkSize defines the subset of the output buffer that we're going to attempt to write to the stream. - // we choose the typical ethernet MTU size here, to align with the expected transport layer characteristics. - const chunkSize = 1500 - // iterate on the output buffer - for startChunkIdx := 0; startChunkIdx < len(w.buffer) && ctx.Err() == nil; { - // slice the output buffer into chunks. - chunkBuf := w.buffer[startChunkIdx:] - if len(chunkBuf) > chunkSize { - chunkBuf = chunkBuf[:chunkSize] - } - // write the chunk to the stream - n, err := rw.Write(chunkBuf) - // if we weren't able to write the chunk due to an error, abort writing. - if err != nil { - break - } - startChunkIdx += n + + if ctx.Err() == nil { + // the following return size/error won't help us much at this point. The request is already finalized. + rw.Write(w.buffer) //nolint:errcheck } }