@@ -56,18 +56,26 @@ func newAPICmd() *cobra.Command {
5656
5757// monitorStdin monitors stdin for EOF, which indicates the parent process has died.
5858// When spawned with piped stdio, stdin closes when the parent process dies.
59+ // The caller is responsible for cancelling the context (e.g. via defer cancel()).
5960func monitorStdin (ctx context.Context , cancel context.CancelFunc , stdin * os.File ) {
60- // Close stdin when context is cancelled to unblock the read
61+ done := make (chan struct {})
62+
63+ // Close stdin when context is cancelled to unblock the read.
64+ // Also exits cleanly when monitorStdin returns.
6165 go func () {
62- <- ctx .Done ()
66+ select {
67+ case <- ctx .Done ():
68+ case <- done :
69+ }
6370 stdin .Close ()
6471 }()
6572
73+ defer close (done )
74+
6675 buf := make ([]byte , 1 )
6776 for {
6877 n , err := stdin .Read (buf )
6978 if err != nil || n == 0 {
70- // Only log and cancel if context isn't already done (parent died)
7179 if ctx .Err () == nil {
7280 slog .Info ("stdin closed, parent process likely died, shutting down" )
7381 cancel ()
@@ -113,10 +121,14 @@ func (f *apiFlags) runAPICommand(cmd *cobra.Command, args []string) error {
113121 }()
114122
115123 // Start recording proxy if --record is specified
116- if _ , cleanup , err := setupRecordingProxy (f .recordPath , & f .runConfig ); err != nil {
124+ if _ , recordCleanup , err := setupRecordingProxy (f .recordPath , & f .runConfig ); err != nil {
117125 return err
118- } else if cleanup != nil {
119- defer cleanup ()
126+ } else if recordCleanup != nil {
127+ defer func () {
128+ if err := recordCleanup (); err != nil {
129+ slog .Error ("Failed to cleanup recording proxy" , "error" , err )
130+ }
131+ }()
120132 }
121133
122134 if f .pullIntervalMins > 0 && ! config .IsOCIReference (agentsPath ) {
0 commit comments