上篇的子进程会写正常数据与独立的诊断流。probe demo.tsv fail 则让固定子脚本明确写 child failed\n 到 STDERR,再 exit 7。run_probe 用 waitpid($pid, 0) 回收进程,从 $? >> 8 取得 7;CLI 将其转为自身退出 2、STDOUT 0 字节、STDERR probe exited 7: child failed\n。子进程 7 与父工具 2 的含义不同,不能直接把 $? 当布尔值打印出去。

另一种错误发生在子程序启动之前:用 run_probe('/definitely/missing/perl-program', 'safe')(仅限库的测试入口)时,open3 抛出 exec of ... failed: No such file or directory;测试校验 probe start failed,而不是伪装成子程序退出 7。输出文本里包含当前文件行号,行号不是稳定外部接口。失败路径均不能输出看起来成功的报表。

图:进程启动、等待与退出状态

1
2
3
exec 失败 -> 没有可解释的子进程退出码 -> start failed
exec 成功 -> 等待结束 -> 分离信号与退出码 -> exit 7 + stderr
exec 成功 -> exit 0 -> stdout 是数据,stderr 仍可有提示

Linux x86_64 下 t/26-31-objects-and-process.t 核对了这些三元组;没有执行 Windows/macOS 的路径、进程启动和信号实验,不能称为跨平台支持。练习:正常子进程向 STDERR 写 probe note,是否必须当作失败?不;成功状态 0 和 stderr 非空可以同时成立,调用契约决定是否转发提示。命令与限制见 examples/perl-language/evidence/26-31.md;参考 Perl 5.38.2 pod/perlfunc.pod 的 waitpid、pod/perlvar.pod 的 $?、pod/perlport.pod 的差异说明。

新增工程测试补了两个原计划中的进程边界:一是临时脚本 kill 'TERM', $$ 后由 run_probe 返回 signal == 15、exit == 0,说明信号终止不能和普通退出码混写;二是把 CLI 的 STDOUT 接到已关闭读端的管道,父进程观察到 SIGPIPE 或非零写失败。这个断言仍限定在当前固定 CLI 和本机管道行为上,不把 IPC::Open3 的顺序读取扩展成通用双流大输出执行器。