From 2f078e0e8cd2b58e4865ee62ce2b950d0550b894 Mon Sep 17 00:00:00 2001 From: garrytan Date: Mon, 2 Nov 2026 22:30:14 +0000 Subject: [PATCH] fix: pre-landing review fixes resumeStopped checks for an exited child before reading ps and names that exit in its error, separately from the 2 s never-stopped timeout. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --- test/cso-snapshot-state.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cso-snapshot-state.test.ts b/test/cso-snapshot-state.test.ts index d69fbc0bd..d957b42de 100644 --- a/test/cso-snapshot-state.test.ts +++ b/test/cso-snapshot-state.test.ts @@ -8,7 +8,7 @@ function repo(){const p=tmp();git(p,'init','-q');git(p,'config','user.email','fi async function waitForPath(file:string,timeout=5000):Promise{const deadline=Date.now()+timeout;while(!fs.existsSync(file)){if(Date.now()>=deadline)throw new Error(`Timed out waiting for ${path.basename(file)}`);await Bun.sleep(5);}} function childExit(child:ReturnType,timeout=5000):Promise{return new Promise((resolve,reject)=>{if(child.exitCode!==null){resolve(child.exitCode);return;}const timer=setTimeout(()=>reject(new Error(`Child ${child.pid} did not exit`)),timeout);child.once('error',error=>{clearTimeout(timer);reject(error);});child.once('close',code=>{clearTimeout(timer);resolve(code);});});} function stopChildren(children:Array>):void{for(const child of children){if(!child.pid||child.exitCode!==null)continue;try{process.kill(child.pid,'SIGCONT');}catch{}try{process.kill(child.pid,'SIGKILL');}catch{}}} -async function resumeStopped(child:ReturnType,timeout=2000):Promise{const deadline=Date.now()+timeout;for(;;){const ps=spawnSync('ps',['-o','stat=','-p',String(child.pid)],{encoding:'utf8',timeout:2000});if(ps.error)throw new Error(`Child ${child.pid} stop check failed: ${ps.error.message}`);if((ps.stdout??'').trim()[0]==='T')break;if(child.exitCode!==null||child.signalCode!==null||Date.now()>=deadline)throw new Error(`Child ${child.pid} marked its pause but never stopped`);await Bun.sleep(5);}process.kill(child.pid!,'SIGCONT');} +async function resumeStopped(child:ReturnType,timeout=2000):Promise{const deadline=Date.now()+timeout;for(;;){if(child.exitCode!==null||child.signalCode!==null)throw new Error(`Child ${child.pid} exited (${child.exitCode??child.signalCode}) after marking its pause, before it stopped`);const ps=spawnSync('ps',['-o','stat=','-p',String(child.pid)],{encoding:'utf8',timeout:2000});if(ps.error)throw new Error(`Child ${child.pid} stop check failed: ${ps.error.message}`);if((ps.stdout??'').trim()[0]==='T')break;if(Date.now()>=deadline)throw new Error(`Child ${child.pid} marked its pause but never stopped`);await Bun.sleep(5);}process.kill(child.pid!,'SIGCONT');} function leaseContenderSource():string{return `import fs from 'node:fs';import * as fsModule from 'node:fs';import * as cryptoModule from 'node:crypto';import path from 'node:path';import {spyOn} from 'bun:test'; const dir=process.env.RACE_DIR!,barrier=process.env.BARRIER!,id=process.env.RACE_ID!,mode=process.env.RACE_MODE??'normal',token=process.env.RACE_TOKEN,leases=path.join(dir,'.mutation-lock-leases'),wait=new Int32Array(new SharedArrayBuffer(4));let triggered=false; const write=fs.writeFileSync.bind(fs),mark=(name,value='ready')=>write(path.join(barrier,name),value,{flag:'wx'}),waitFor=(name)=>{const deadline=Date.now()+5000;while(!fs.existsSync(path.join(barrier,name))){if(Date.now()>=deadline)throw new Error('barrier timeout: '+name);Atomics.wait(wait,0,0,1);}};