diff --git a/internal/tools/exec_workspace.go b/internal/tools/exec_workspace.go index c996cbe..765f2e1 100644 --- a/internal/tools/exec_workspace.go +++ b/internal/tools/exec_workspace.go @@ -386,6 +386,8 @@ func relaxAndRemove(root string) { return nil // 清理尽力而为:失败留给会话目录清理兜底 }) _ = os.RemoveAll(root) + // -ws 根目录在空时顺手移除(每会话一个壳,不清理会随会话累积)。 + _ = os.Remove(filepath.Dir(root)) } func (p *overlayProcess) Kill() error { return p.inner.Kill() } diff --git a/internal/tools/exec_workspace_test.go b/internal/tools/exec_workspace_test.go index 26a2f9a..ab9de17 100644 --- a/internal/tools/exec_workspace_test.go +++ b/internal/tools/exec_workspace_test.go @@ -231,3 +231,25 @@ func TestSandboxWorkspaceOverlayTimeoutDiscards(t *testing.T) { } func shortTimeout() time.Duration { return 1500 * time.Millisecond } + +// -ws 壳目录在空时移除(不随会话累积)。 +func TestOverlayCleansShellDir(t *testing.T) { + if _, err := exec.LookPath("bwrap"); err != nil { + t.Skip("bwrap not available") + } + old := workspaceOverlay + workspaceOverlay = true + defer func() { workspaceOverlay = old }() + dir := t.TempDir() + spec := ExecSpec{Bin: "/bin/bash", Args: []string{"-c", "echo hi"}, Dir: dir, Env: []string{"PATH=/usr/bin:/bin"}} + proc, err := sandboxBackend{}.Start(context.Background(), spec, &strings.Builder{}) + if err != nil { + t.Fatal(err) + } + if err := proc.Wait(); err != nil { + t.Fatal(err) + } + if _, serr := os.Stat(dir + "-ws"); !os.IsNotExist(serr) { + t.Fatalf("-ws shell dir must be removed when empty: %v", serr) + } +}