修复AI游戏创作跨平台运行竞态
Project CI / Repository checks (pull_request) Successful in 1m26s
Project CI / Backend tests (pull_request) Successful in 4m18s
Project CI / Native shell tests (pull_request) Successful in 12m18s
Project CI / Frontend tests (pull_request) Successful in 1m25s

保存独立进程组标识并在启动失败或退出时清理后代进程

兼容macOS下带前置选项的npm脚本命令校验

修复进程会话输出上限投影、测试夹具与锁污染问题

收敛Agent运行时lane释放、并发锁初始化与异步审计时序竞态

补充Node与Native Shell回归测试并同步排障文档
This commit is contained in:
2026-07-22 20:27:43 +08:00
parent e662e61c40
commit 4494153104
9 changed files with 257 additions and 66 deletions
@@ -187,7 +187,13 @@ function spawnChild(command, args, options, spawnImpl = spawn) {
detached: !useShell,
stdio: 'inherit',
});
const lifecycle = { failure: null, promise: null };
const lifecycle = {
failure: null,
promise: null,
// detached 子进程在 POSIX 下以自身 PID 作为 PGID。leader 退出后
// child.pid 仍是清理其后代的唯一稳定句柄,必须随生命周期保留。
processGroupId: !useShell && Number.isInteger(child.pid) ? child.pid : null,
};
lifecycle.promise = new Promise((resolveLifecycle) => {
child.once('error', (error) => {
lifecycle.failure = { type: 'error', error };
@@ -231,21 +237,36 @@ function formatChildFailure(failure) {
}
function stopChild(child, signal = 'SIGTERM') {
if (!child || child.exitCode != null || child.signalCode != null) {
if (!child) {
return;
}
if (process.platform !== 'win32') {
const processGroupId = childLifecycles.get(child)?.processGroupId;
if (Number.isInteger(processGroupId)) {
try {
process.kill(-processGroupId, signal);
return;
} catch (error) {
if (error?.code === 'ESRCH') {
return;
}
// leader 尚存活时保留 direct child fallback;leader 已退出则仍以
// 负 PGID kill 的失败为准,不能误以为 descendants 已清理。
if (child.exitCode != null || child.signalCode != null) {
return;
}
}
}
}
if (child.exitCode != null || child.signalCode != null) {
return;
}
try {
if (process.platform !== 'win32' && Number.isInteger(child.pid)) {
process.kill(-child.pid, signal);
} else {
child.kill(signal);
}
child.kill(signal);
} catch {
try {
child.kill(signal);
} catch {
// ignore cleanup races
}
// ignore cleanup races
}
}