From 45953b3d9c250658767aa6bb673422f8d954b950 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Fri, 14 Nov 2025 21:43:34 +0900 Subject: [PATCH] ldd: cancel on decoder error This prevents blocking from failures caused by ldd(1) emitting output that is not anticipated by the decoder. Signed-off-by: Ophestra --- ldd/exec.go | 5 +++++ ldd/exec_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 ldd/exec_test.go diff --git a/ldd/exec.go b/ldd/exec.go index d91cd65..959a3f4 100644 --- a/ldd/exec.go +++ b/ldd/exec.go @@ -68,6 +68,11 @@ func Exec(ctx context.Context, msg message.Msg, p string) ([]*Entry, error) { } entries, decodeErr := d.Decode() + if decodeErr != nil { + // do not cancel on successful decode to avoid racing with ldd(1) termination + cancel() + } + if err := z.Wait(); err != nil { m := stderr.Bytes() if bytes.Contains(m, []byte(msgStaticSuffix)) || bytes.Contains(m, []byte(msgStaticGlibc)) { diff --git a/ldd/exec_test.go b/ldd/exec_test.go new file mode 100644 index 0000000..a6d3a7e --- /dev/null +++ b/ldd/exec_test.go @@ -0,0 +1,45 @@ +package ldd_test + +import ( + "errors" + "os" + "os/exec" + "testing" + + "hakurei.app/container" + "hakurei.app/ldd" + "hakurei.app/message" +) + +func TestExec(t *testing.T) { + t.Parallel() + + t.Run("failure", func(t *testing.T) { + t.Parallel() + + _, err := ldd.Exec(t.Context(), nil, "/proc/nonexistent") + + var exitError *exec.ExitError + if !errors.As(err, &exitError) { + t.Fatalf("Exec: error has incorrect concrete type: %#v", err) + } + + const want = 1 + if got := exitError.ExitCode(); got != want { + t.Fatalf("Exec: ExitCode = %d, want %d", got, want) + } + }) + + t.Run("success", func(t *testing.T) { + msg := message.New(nil) + msg.GetLogger().SetPrefix("check: ") + if entries, err := ldd.Exec(t.Context(), nil, container.MustExecutable(msg)); err != nil { + t.Fatalf("Exec: error = %v", err) + } else if testing.Verbose() { + // result cannot be measured here as build information is not known + t.Logf("Exec: %q", entries) + } + }) +} + +func TestMain(m *testing.M) { container.TryArgv0(nil); os.Exit(m.Run()) }