From 502f4d116717d46cfec04f3cf696a5eea9e7fcf6 Mon Sep 17 00:00:00 2001 From: lucarin91 Date: Mon, 17 Nov 2025 15:13:45 +0100 Subject: [PATCH 1/3] fix(pkg/board): wait for zombie process in adb --- pkg/board/remote/adb/adb.go | 2 ++ pkg/board/remote/adb/adb_nowindows.go | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/pkg/board/remote/adb/adb.go b/pkg/board/remote/adb/adb.go index 6efdb1f4..3d7575b2 100644 --- a/pkg/board/remote/adb/adb.go +++ b/pkg/board/remote/adb/adb.go @@ -120,6 +120,7 @@ func (a *ADBConnection) List(path string) ([]remote.FileInfo, error) { if err := cmd.Start(); err != nil { return nil, err } + defer cmd.Wait() r := bufio.NewReader(output) _, err = r.ReadBytes('\n') // Skip the first line @@ -167,6 +168,7 @@ func (a *ADBConnection) Stats(p string) (remote.FileInfo, error) { if err := cmd.Start(); err != nil { return remote.FileInfo{}, err } + defer cmd.Wait() r := bufio.NewReader(output) line, err := r.ReadBytes('\n') diff --git a/pkg/board/remote/adb/adb_nowindows.go b/pkg/board/remote/adb/adb_nowindows.go index 32699417..432fdb54 100644 --- a/pkg/board/remote/adb/adb_nowindows.go +++ b/pkg/board/remote/adb/adb_nowindows.go @@ -37,6 +37,11 @@ func adbReadFile(a *ADBConnection, path string) (io.ReadCloser, error) { if err := cmd.Start(); err != nil { return nil, err } + defer func() { + go func() { + _ = cmd.Wait() + }() + }() return output, nil } From 503fa9cbe638307ca0fa4f3770475c29234d78d1 Mon Sep 17 00:00:00 2001 From: lucarin91 Date: Mon, 17 Nov 2025 15:35:50 +0100 Subject: [PATCH 2/3] make linter happy --- pkg/board/remote/adb/adb.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/board/remote/adb/adb.go b/pkg/board/remote/adb/adb.go index 3d7575b2..3ec28b13 100644 --- a/pkg/board/remote/adb/adb.go +++ b/pkg/board/remote/adb/adb.go @@ -120,7 +120,7 @@ func (a *ADBConnection) List(path string) ([]remote.FileInfo, error) { if err := cmd.Start(); err != nil { return nil, err } - defer cmd.Wait() + defer func() { _ = cmd.Wait() }() r := bufio.NewReader(output) _, err = r.ReadBytes('\n') // Skip the first line @@ -168,7 +168,7 @@ func (a *ADBConnection) Stats(p string) (remote.FileInfo, error) { if err := cmd.Start(); err != nil { return remote.FileInfo{}, err } - defer cmd.Wait() + defer func() { _ = cmd.Wait() }() r := bufio.NewReader(output) line, err := r.ReadBytes('\n') From 2f3be2928ff46023e6e8aec1954f538cecb04004 Mon Sep 17 00:00:00 2001 From: lucarin91 Date: Mon, 17 Nov 2025 18:19:18 +0100 Subject: [PATCH 3/3] user a better way to handler wait on close --- pkg/board/remote/adb/adb_nowindows.go | 17 +++++++++++------ pkg/board/remote/adb/adb_windows.go | 4 ++-- pkg/board/remote/remote.go | 14 ++++++++++++++ pkg/board/remote/ssh/ssh.go | 14 +------------- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/pkg/board/remote/adb/adb_nowindows.go b/pkg/board/remote/adb/adb_nowindows.go index 432fdb54..e856b9e2 100644 --- a/pkg/board/remote/adb/adb_nowindows.go +++ b/pkg/board/remote/adb/adb_nowindows.go @@ -18,11 +18,14 @@ package adb import ( + "cmp" "context" "fmt" "io" "github.com/arduino/go-paths-helper" + + "github.com/arduino/arduino-app-cli/pkg/board/remote" ) func adbReadFile(a *ADBConnection, path string) (io.ReadCloser, error) { @@ -37,12 +40,14 @@ func adbReadFile(a *ADBConnection, path string) (io.ReadCloser, error) { if err := cmd.Start(); err != nil { return nil, err } - defer func() { - go func() { - _ = cmd.Wait() - }() - }() - return output, nil + return remote.WithCloser{ + Reader: output, + CloseFun: func() error { + err1 := output.Close() + err2 := cmd.Wait() + return cmp.Or(err1, err2) + }, + }, nil } func adbWriteFile(a *ADBConnection, r io.Reader, pathStr string) error { diff --git a/pkg/board/remote/adb/adb_windows.go b/pkg/board/remote/adb/adb_windows.go index 26b752a5..150d9cc0 100644 --- a/pkg/board/remote/adb/adb_windows.go +++ b/pkg/board/remote/adb/adb_windows.go @@ -26,7 +26,7 @@ import ( "github.com/arduino/go-paths-helper" - "github.com/arduino/arduino-app-cli/pkg/board/remote/ssh" + "github.com/arduino/arduino-app-cli/pkg/board/remote" ) func adbReadFile(a *ADBConnection, path string) (io.ReadCloser, error) { @@ -44,7 +44,7 @@ func adbReadFile(a *ADBConnection, path string) (io.ReadCloser, error) { return nil, err } - return ssh.WithCloser{ + return remote.WithCloser{ Reader: decoded, CloseFun: func() error { err1 := output.Close() diff --git a/pkg/board/remote/remote.go b/pkg/board/remote/remote.go index 9330610a..247e7718 100644 --- a/pkg/board/remote/remote.go +++ b/pkg/board/remote/remote.go @@ -59,3 +59,17 @@ type Cmder interface { Output(ctx context.Context) ([]byte, error) Interactive() (io.WriteCloser, io.Reader, io.Reader, Closer, error) } + +// WithCloser is a helper to create an io.ReadCloser from an io.Reader +// and a close function. +type WithCloser struct { + io.Reader + CloseFun func() error +} + +func (w WithCloser) Close() error { + if w.CloseFun != nil { + return w.CloseFun() + } + return nil +} diff --git a/pkg/board/remote/ssh/ssh.go b/pkg/board/remote/ssh/ssh.go index cca231f5..9b14d8f4 100644 --- a/pkg/board/remote/ssh/ssh.go +++ b/pkg/board/remote/ssh/ssh.go @@ -219,18 +219,6 @@ func (a *SSHConnection) WriteFile(r io.Reader, path string) error { return nil } -type WithCloser struct { - io.Reader - CloseFun func() error -} - -func (w WithCloser) Close() error { - if w.CloseFun != nil { - return w.CloseFun() - } - return nil -} - func (a *SSHConnection) ReadFile(path string) (io.ReadCloser, error) { session, err := a.client.NewSession() if err != nil { @@ -247,7 +235,7 @@ func (a *SSHConnection) ReadFile(path string) (io.ReadCloser, error) { return nil, fmt.Errorf("failed to start command: %w", err) } - return WithCloser{ + return remote.WithCloser{ Reader: output, CloseFun: session.Close, }, nil