From c1436e5364f236e148cfd65c77fe86b2eefd4bdb Mon Sep 17 00:00:00 2001 From: MD YUNUS Date: Sun, 15 Mar 2026 16:33:46 +0530 Subject: [PATCH 1/2] fix: propagate cleanup errors in defer functions --- cmd/root/api.go | 22 ++++++++++++++++++++-- cmd/root/run.go | 11 ++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/cmd/root/api.go b/cmd/root/api.go index f4ce5501f..804a059b2 100644 --- a/cmd/root/api.go +++ b/cmd/root/api.go @@ -46,7 +46,7 @@ func newAPICmd() *cobra.Command { return cmd } -func (f *apiFlags) runAPICommand(cmd *cobra.Command, args []string) error { +func (f *apiFlags) runAPICommand(cmd *cobra.Command, args []string) (retErr error) { telemetry.TrackCommand("serve", append([]string{"api"}, args...)) ctx := cmd.Context() @@ -65,6 +65,10 @@ func (f *apiFlags) runAPICommand(cmd *cobra.Command, args []string) error { defer func() { if err := cleanup(); err != nil { slog.Error("Failed to cleanup fake proxy", "error", err) + // Only set return error if no other error occurred + if retErr == nil { + retErr = fmt.Errorf("failed to cleanup fake proxy: %w", err) + } } }() @@ -76,6 +80,10 @@ func (f *apiFlags) runAPICommand(cmd *cobra.Command, args []string) error { defer func() { if err := recordCleanup(); err != nil { slog.Error("Failed to cleanup recording proxy", "error", err) + // Only set return error if no other error occurred + if retErr == nil { + retErr = fmt.Errorf("failed to cleanup recording proxy: %w", err) + } } }() @@ -87,7 +95,14 @@ func (f *apiFlags) runAPICommand(cmd *cobra.Command, args []string) error { if err != nil { return err } - defer lnCleanup() + defer func() { + if err := lnCleanup(); err != nil { + slog.Error("Failed to cleanup listener", "error", err) + if retErr == nil { + retErr = fmt.Errorf("failed to cleanup listener: %w", err) + } + } + }() out.Println("Listening on", ln.Addr().String()) @@ -106,6 +121,9 @@ func (f *apiFlags) runAPICommand(cmd *cobra.Command, args []string) error { defer func() { if err := sessionStore.Close(); err != nil { slog.Error("Failed to close session store", "error", err) + if retErr == nil { + retErr = fmt.Errorf("failed to close session store: %w", err) + } } }() diff --git a/cmd/root/run.go b/cmd/root/run.go index 52eef0751..a5648570d 100644 --- a/cmd/root/run.go +++ b/cmd/root/run.go @@ -141,7 +141,7 @@ func (f *runExecFlags) runRunCommand(cmd *cobra.Command, args []string) error { return f.runOrExec(ctx, out, args, useTUI) } -func (f *runExecFlags) runOrExec(ctx context.Context, out *cli.Printer, args []string, useTUI bool) error { +func (f *runExecFlags) runOrExec(ctx context.Context, out *cli.Printer, args []string, useTUI bool) (retErr error) { slog.Debug("Starting agent", "agent", f.agentName) // Start CPU profiling if requested @@ -216,6 +216,9 @@ func (f *runExecFlags) runOrExec(ctx context.Context, out *cli.Printer, args []s defer func() { if err := fakeCleanup(); err != nil { slog.Error("Failed to cleanup fake proxy", "error", err) + if retErr == nil { + retErr = fmt.Errorf("failed to cleanup fake proxy: %w", err) + } } }() @@ -228,6 +231,9 @@ func (f *runExecFlags) runOrExec(ctx context.Context, out *cli.Printer, args []s defer func() { if err := recordCleanup(); err != nil { slog.Error("Failed to cleanup recording proxy", "error", err) + if retErr == nil { + retErr = fmt.Errorf("failed to cleanup recording proxy: %w", err) + } } }() out.Println("Recording mode enabled, cassette: " + cassettePath) @@ -260,6 +266,9 @@ func (f *runExecFlags) runOrExec(ctx context.Context, out *cli.Printer, args []s defer func() { if err := rt.Close(); err != nil { slog.Error("Failed to close runtime", "error", err) + if retErr == nil { + retErr = fmt.Errorf("failed to close runtime: %w", err) + } } }() var initialTeamCleanupOnce sync.Once From e0fc504195dacb9af08a27b6a54d9a515437b496 Mon Sep 17 00:00:00 2001 From: MD YUNUS Date: Sun, 15 Mar 2026 16:54:56 +0530 Subject: [PATCH 2/2] fix: remove redundant listener close in cleanup function --- cmd/root/flags.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cmd/root/flags.go b/cmd/root/flags.go index ea352b35d..857cf2a41 100644 --- a/cmd/root/flags.go +++ b/cmd/root/flags.go @@ -133,9 +133,8 @@ func parseModelShorthand(s string) *latest.ModelConfig { } // newListener creates a TCP listener and returns a cleanup function that -// must be deferred by the caller. The cleanup function closes the listener. -// The listener is also closed if the context is cancelled, which unblocks -// any in-progress Serve call. +// must be deferred by the caller. The cleanup function triggers the +// context.AfterFunc to close the listener. func newListener(ctx context.Context, addr string) (net.Listener, func(), error) { ln, err := server.Listen(ctx, addr) if err != nil { @@ -146,7 +145,6 @@ func newListener(ctx context.Context, addr string) (net.Listener, func(), error) }) cleanup := func() { stop() - _ = ln.Close() } return ln, cleanup, nil }