Execute the managed interpreter through its real path
ci / vet-and-test (pull_request) Successful in 1m3s
ci / vet-and-test (pull_request) Successful in 1m3s
Why: the sandbox hides /home and only remounts the resolved Python prefix, so executing python/current/bin/python3 failed before the base layer could be imported. Evidence: go test ./internal/tools/ -run TestResolveInterpreterFollowsManagedSymlink passed, and env doctor against the built base layer printed doctor ok (SELF). Impact: run_python and env doctor follow the symlink into the mounted prefix or /usr/bin/python3. The layer and the prefix mount stay the same. Refs: Agent-System-Backend PR 207 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"agent-system-backend/internal/execenv"
|
"agent-system-backend/internal/execenv"
|
||||||
@@ -137,6 +138,9 @@ func runDoctor(ctx context.Context, root *execenv.Root, py string, sandbox bool)
|
|||||||
if prefix := root.PythonPrefix(); prefix != "" {
|
if prefix := root.PythonPrefix(); prefix != "" {
|
||||||
mounts = append(mounts, prefix)
|
mounts = append(mounts, prefix)
|
||||||
}
|
}
|
||||||
|
if resolved, err := filepath.EvalSymlinks(py); err == nil {
|
||||||
|
py = resolved
|
||||||
|
}
|
||||||
if err := execenv.Doctor(ctx, py, pyPath, nil, sandbox, mounts); err != nil {
|
if err := execenv.Doctor(ctx, py, pyPath, nil, sandbox, mounts); err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "env doctor:", err)
|
fmt.Fprintln(os.Stderr, "env doctor:", err)
|
||||||
return 1
|
return 1
|
||||||
|
|||||||
@@ -203,7 +203,13 @@ func resolveInterpreter(name string) (string, error) {
|
|||||||
case "python3":
|
case "python3":
|
||||||
if execPythonBin != "" {
|
if execPythonBin != "" {
|
||||||
if st, err := os.Stat(execPythonBin); err == nil && !st.IsDir() {
|
if st, err := os.Stat(execPythonBin); err == nil && !st.IsDir() {
|
||||||
return execPythonBin, nil
|
// current/bin/python3 是符号链接。沙箱用 tmpfs 盖住 /home 后只挂真实前缀,
|
||||||
|
// 执行未解析的 current 路径会找不到文件。
|
||||||
|
resolved, err := filepath.EvalSymlinks(execPythonBin)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return resolved, nil
|
||||||
}
|
}
|
||||||
return "", fmt.Errorf("python3: configured interpreter missing: %s", execPythonBin)
|
return "", fmt.Errorf("python3: configured interpreter missing: %s", execPythonBin)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -213,6 +213,28 @@ func TestExecEnvIncludesSkillsRoot(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestResolveInterpreterFollowsManagedSymlink(t *testing.T) {
|
||||||
|
prev := execPythonBin
|
||||||
|
t.Cleanup(func() { execPythonBin = prev })
|
||||||
|
dir := t.TempDir()
|
||||||
|
link := filepath.Join(dir, "python3")
|
||||||
|
if err := os.Symlink("/usr/bin/python3", link); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
execPythonBin = link
|
||||||
|
got, err := resolveInterpreter("python3")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
want, err := filepath.EvalSymlinks("/usr/bin/python3")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if got != want {
|
||||||
|
t.Fatalf("resolved %q, want %q", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestInterpreterExecConfigForKernel(t *testing.T) {
|
func TestInterpreterExecConfigForKernel(t *testing.T) {
|
||||||
cfg := InterpreterExecConfig()
|
cfg := InterpreterExecConfig()
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user