wandering1
|
1b450be0ef
|
fix(skill): @build 自持自释 build 锁,根治忘记 release 的泄漏
问题:锁不绑定进程存活(`lock acquire` 是短命进程,真正用 UV4 的是另一个
进程),所以释放只能靠调用方记得。Agent 手工 `lock acquire build` 后忘
了 `release`,锁要挂到 6 小时 TTL 才被下次 acquire 接管——期间其他任务
要么立即失败、要么干等。`done` 自己已用 try/finally 兜住,但手工路径没有。
改法:让**用资源的人**持锁。`keil_build.py` 进入 acquire、`finally`
**无条件** release(构建失败 / 异常 / SystemExit 都会释放)。
- `--lock-task`:持有者名。默认 `$DTU_TASK_ID` → 从 cwd 的
`_wt/<ID>-<slug>/` 反推 `<ID>` → `build-cli`。反推意味着"手工
`lock acquire build --task <ID>` 后再跑 @build"仍幂等,不会自我死锁。
- `--lock-wait N`:锁被占时等待(默认 0 = 立即失败)。
- `--no-lock`:完全不加锁。
- 新增退出码 **4 = build 锁被占用**(原先无此语义,占用会直接去构建)。
- 锁工具 = 兄弟 skill `task-worktree`;**找不到则降级为不加锁并告警**,
保持本 skill 可独立搬运。
`done` 的兼容处理:它自己持锁,给子进程设 `DTU_LOCK_HELD=build` 告知
跳过自持自释。**对"工作树里还是旧 keil_build.py"的在途任务同样安全**
——旧版根本不看该变量、也不会自锁,故不会出现"双重持锁"死锁。
`bench` 锁**不动**:它是**会话作用域**(跨烧录→@test→探针多条命令),
逐命令自动释放会让别的任务插进来扰动设备,必须继续由 Agent 持有。
验证(主工作树实测):
- 自持自释:acquire → BUILD_OK → release,前后 `lock status` 均空闲;
- 被占:由 other-task 占锁 → exit 4,且**未触发构建**;
- 调用方持锁:`DTU_LOCK_HELD=build` → 打印"跳过自持自释",且
**未释放调用方的锁**(锁仍归 __done__)——关键安全性质;
- 错误路径:无调用方持锁 + `--project` 不存在 → 失败但 **finally 已释放**;
- 持有者名推导:主工作树 → `build-cli`,`_wt/N33-stack-margins` → `N33`;
- 门禁:`mem-numbers` 一致;pre-commit 全绿。
|
2026-10-12 18:07:58 +08:00 |
|