# 一条关于「超时」的工程笔记。 一次单测在 600 秒处被硬停,留下的记录只有一句… > 一条关于「超时」的工程笔记。 一次单测在 600 秒处被硬停,留下的记录只有一句:测试没有运行。这其实是最诚实的一种结果——被时钟掐断的运行没有产生裁决,它既不该记成"失败",更不 - Canonical page: https://obelisk.club/blog/build-log-524 - Author: Peter Zhang - Published: 2026-10-11 - Tags: build-log 一条关于「超时」的工程笔记。 一次单测在 600 秒处被硬停,留下的记录只有一句:测试没有运行。这其实是最诚实的一种结果——被时钟掐断的运行没有产生裁决,它既不该记成"失败",更不该记成通过。真正的麻烦在于:超时是一个把原因删掉了的症状。从未启动的测试、卡在没人应答的调用上的测试、单纯装不进时限的测试,留下的记录一模一样;原样重跑,只会原样复现这个"非裁决"。 这类问题为什么能长期隐形:绿灯只说"过了",从不说离时钟上限还有多少余量。套件一个月一个月悄悄变重,直到某天没有任何代码改动,它"突然"超时;而一旦记录层把超时写成带原因的失败,下一个动作就会变成去 debug 代码——可机器根本没裁决过这份代码。 修法有先后,顺序本身是承重的: 1. 先恢复被时钟删掉的信息:被杀前的最后输出、部分副作用、到底有没有推进。去读"执行了 N 条测试"那一行,别读结论标记——执行数为零的绿灯什么也没证明。 2. 再区分"卡住"与"装不下"。每次都死在同一个固定上限,是装不下:把套件拆成能跑完的块,并给每条测试独立时限——整组共享一个时钟,等于让最重的那条替所有轻的做裁决。完全没推进、也不烧 CPU,是卡住:进程活着但没在工作,加多少预算都没用;第一嫌疑永远是主线程上的同步系统调用——测试宿主里,通知、钥匙串那类守护进程永远不会回包,主线程等它就是无限期。挂起窗口里用进程采样器抓几秒,能直接定位到文件和行,转录日志永远不会。 3. 最后上护栏:被上限掐断的运行必须记为"无裁决",永远不许伪装成带原因的失败;执行数为零的"通过"一律无效。 一分钟自检:翻出你最近一次测试日志,找到执行条数那一行,看数字是多少;再给整套测试掐一次表,和运行环境的时限比一比——如果余量只剩一半,今天就给每条测试加上独立时限。这两个数字,绿灯永远不会替你看。