Aias00 opened a new pull request, #3547:
URL: https://github.com/apache/dubbo-go/pull/3547

   ## What
   
   `handlePkg` serves many keep-alive requests in a `for` loop; each request 
with a `Timeout` header created a `context.WithTimeout` whose `cancel` was 
`defer`d **inside the loop**, so defers (and the retained contexts/timers) 
accumulated for the connection's lifetime — a slow memory leak under sustained 
keep-alive traffic.
   
   ## Why
   
   ```go
   // protocol/jsonrpc/server.go handlePkg, per request in the for-loop (before)
   if len(reqHeader["Timeout"]) > 0 {
       timeout, err := time.ParseDuration(reqHeader["Timeout"])
       if err == nil {
           httpTimeout = timeout
           var cancel context.CancelFunc
           ctx, cancel = context.WithTimeout(ctx, httpTimeout)
           defer cancel()   // <-- defer inside a loop, in a long-lived fn
       }
       delete(reqHeader, "Timeout")
   }
   ```
   
   `defer` only runs when `handlePkg` returns (connection close), so each 
keep-alive request with a `Timeout` header accumulates one deferred `cancel` + 
retained context/timer. A persistent connection sending many timed requests 
grows the defer chain unbounded → slow memory growth / eventual OOM. The `ctx` 
is also not cancelled promptly after `serveRequest` returns.
   
   ## Fix
   
   Call `cancel` explicitly after `serveRequest` returns (declared outside the 
`if`):
   
   ```go
   var cancel context.CancelFunc
   if len(reqHeader["Timeout"]) > 0 {
       timeout, err := time.ParseDuration(reqHeader["Timeout"])
       if err == nil { httpTimeout = timeout; ctx, cancel = 
context.WithTimeout(ctx, httpTimeout) }
       delete(reqHeader, "Timeout")
   }
   setTimeout(conn, httpTimeout)
   serveErr := serveRequest(ctx, reqHeader, reqBody, conn)
   if cancel != nil { cancel() }
   if serveErr != nil { ...; return }
   ```
   
   ## Tests
   
   Existing jsonrpc tests pass (the request-serving behavior is unchanged; the 
fix is a scoped cancel-vs-defer change). A direct leak assertion isn't added 
because defer accumulation isn't observable without a heap-profile harness; the 
change is obviously correct (defer-in-loop → explicit call) and 
behavior-preserving.
   
   Fixes #3546


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to