AlexStocks opened a new issue, #3555:
URL: https://github.com/apache/dubbo-go/issues/3555
## Description
Several goroutines and retry loops have no cancellation / context-exit path,
so they can leak or block indefinitely when the component is shutting down or
the upstream is unavailable.
## Affected locations
### 1. `cluster/cluster/failback/cluster_invoker.go` — `process` (L94-L121)
```go
func (invoker *failbackClusterInvoker) process(ctx context.Context) {
invoker.ticker = time.NewTicker(time.Second * 1)
for range invoker.ticker.C { // L96: no ctx.Done() branch
for {
value, err := invoker.taskList.Peek()
if err == queue.ErrDisposed { return }
...
go invoker.tryTimerTaskProc(ctx, retryTask) // L118
}
}
}
```
- `ctx` is passed in but never selected on; the only exit is
`taskList.Dispose()`.
- The ticker has no `defer invoker.ticker.Stop()`.
- Risk: if `Dispose` is never called, the goroutine (and the ticker) leak
for the process lifetime.
### 2. `registry/base_registry.go` — `Subscribe` (L330-L347)
```go
for { // L330: no ctx exit
if !r.IsAvailable() { return ... }
listener, err := r.facadeBasedRegistry.DoSubscribe(url)
if err != nil { time.Sleep(...); continue } // L343: unbounded retry,
no ctx cancel
for { ... } // L347: inner loop also has no ctx
}
```
- No upper bound on retries; cannot be cancelled by an external `context`.
- Risk: a permanently unavailable registry causes an infinite blocking retry
loop.
### 3. `remoting/getty/pool.go` — connect loop (L81-L97)
```go
for {
idx++
if c.isAvailable() { break }
if time.Since(start) > connectTimeout { ... return }
interval := time.Millisecond * time.Duration(idx)
time.Sleep(interval) // L96: blocks; cannot react to ctx
cancel
}
```
- Uses `time.Sleep` polling instead of `select` + `ctx.Done()`; a cancelled
context still waits for the sleep to return.
- Risk: connection attempts cannot be interrupted promptly.
## Suggested fix
- `failback`: `defer invoker.ticker.Stop()`; add `select { case
<-ctx.Done(): return; case <-invoker.ticker.C: ... }`.
- `base_registry`: select on `ctx.Done()` in the retry loops and return on
cancellation.
- `getty/pool`: replace the `time.Sleep` polling with `select { case
<-ctx.Done(): return; case <-time.After(interval): }`.
## Severity
P0/P1 — goroutine leak + non-cancellable retry loops affect long-running
service stability.
## Environment
- Reproducible on current `develop` tip (3.3.2 prep).
--
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]