fix(app): fix goroutine leak, shutdown context, and model matching (#2298)
huaiyuWangh
created 2 weeks ago
- Add missing return after error send in RunNonInteractive goroutine
- Use context.WithoutCancel for shutdown to preserve tracing context
- Use strings.EqualFold for case-insensitive model matching
- Preserve LSP ConnectedAt across state transitions
Change summary
internal/app/app.go | 3 ++-
internal/app/lsp_events.go | 2 ++
internal/app/provider.go | 4 ++--
3 files changed, 6 insertions(+), 3 deletions(-)
Detailed changes
@@ -246,6 +246,7 @@ func (app *App) RunNonInteractive(ctx context.Context, output io.Writer, prompt,
done <- response{
err: fmt.Errorf("failed to start agent processing stream: %w", err),
}
+ return
}
done <- response{
result: result,
@@ -551,7 +552,7 @@ func (app *App) Shutdown() {
var wg sync.WaitGroup
// Shared shutdown context for all timeout-bounded cleanup.
- shutdownCtx, cancel := context.WithTimeout(app.globalCtx, 5*time.Second)
+ shutdownCtx, cancel := context.WithTimeout(context.WithoutCancel(app.globalCtx), 5*time.Second)
defer cancel()
// Send exit event
@@ -67,6 +67,8 @@ func updateLSPState(name string, state lsp.ServerState, err error, client *lsp.C
}
if state == lsp.StateReady {
info.ConnectedAt = time.Now()
+ } else if existing, ok := lspStates.Get(name); ok {
+ info.ConnectedAt = existing.ConnectedAt
}
lspStates.Set(name, info)
@@ -70,8 +70,8 @@ func findModels(providers map[string]config.ProviderConfig, largeModel, smallMod
}
func filter(modelFilter, providerFilter, model, provider string) bool {
- return modelFilter != "" && model == modelFilter &&
- (providerFilter == "" || provider == providerFilter)
+ return modelFilter != "" && strings.EqualFold(model, modelFilter) &&
+ (providerFilter == "" || strings.EqualFold(provider, providerFilter))
}
// Validate and return a single match.