Skip to content

Commit 3494e55

Browse files
committed
fix: make release validation portable on Linux
1 parent f951532 commit 3494e55

3 files changed

Lines changed: 44 additions & 3 deletions

File tree

‎scripts/lib/real-codex-host-probe.js‎

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,16 +1514,41 @@ function finalizeAttempt(attemptRef, details) {
15141514
return JSON.parse(fs.readFileSync(target, 'utf8'))
15151515
}
15161516

1517-
function isPidAlive(pid) {
1517+
function isPidAlive(pid, options = {}) {
15181518
if (!Number.isInteger(pid) || pid <= 0) return false
1519+
const platform = options.platform || process.platform
1520+
const fsImpl = options.fs || fs
1521+
const kill = options.kill || process.kill.bind(process)
1522+
if (platform === 'linux') {
1523+
try {
1524+
const stat = fsImpl.readFileSync(`/proc/${pid}/stat`, 'utf8')
1525+
const nameEnd = stat.lastIndexOf(')')
1526+
const state = nameEnd >= 0 ? stat.slice(nameEnd + 1).trimStart()[0] : ''
1527+
if (state === 'Z' || state === 'X') return false
1528+
} catch (error) {
1529+
if (error?.code === 'ENOENT') return false
1530+
}
1531+
}
15191532
try {
1520-
process.kill(pid, 0)
1533+
kill(pid, 0)
15211534
return true
15221535
} catch (error) {
15231536
return error?.code === 'EPERM'
15241537
}
15251538
}
15261539

1540+
const PID_EXIT_WAIT_SIGNAL = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT))
1541+
1542+
function waitForPidExit(pid, timeoutMs = 1000) {
1543+
const deadline = Date.now() + timeoutMs
1544+
while (isPidAlive(pid)) {
1545+
const remaining = deadline - Date.now()
1546+
if (remaining <= 0) return false
1547+
Atomics.wait(PID_EXIT_WAIT_SIGNAL, 0, 0, Math.min(25, remaining))
1548+
}
1549+
return true
1550+
}
1551+
15271552
function isOwnedCleanupComplete(cleanup) {
15281553
if (!cleanup || cleanup.stillRunning === true) return false
15291554
if (cleanup.attempted !== true) return true
@@ -1549,14 +1574,17 @@ function terminateOwnedProcessTree(pid) {
15491574
result = { status: null, signal: null, error, stdout: '', stderr: '' }
15501575
}
15511576
}
1577+
const stillRunning = process.platform === 'win32'
1578+
? isPidAlive(pid)
1579+
: !waitForPidExit(pid)
15521580
return {
15531581
attempted: true,
15541582
method: process.platform === 'win32' ? 'taskkill-exact-pid-tree' : 'kill-exact-process-group',
15551583
pid,
15561584
exitCode: result.status,
15571585
signal: result.signal || null,
15581586
errorCode: result.error?.code || null,
1559-
stillRunning: isPidAlive(pid)
1587+
stillRunning
15601588
}
15611589
}
15621590

@@ -2753,6 +2781,7 @@ module.exports = {
27532781
isNonterminalH3SafePartial,
27542782
isOwnedCleanupComplete,
27552783
isPathInside,
2784+
isPidAlive,
27562785
main,
27572786
normalizeObservedCommand,
27582787
normalizeObservedCommandVariants,

‎scripts/lib/skill-route-test-fixture.js‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ function createSkillRouteFixture (options = {}) {
200200
inputRoot: root,
201201
workspaceRoot: root,
202202
packageRoot: PACKAGE_ROOT,
203+
globalSkillsRoot: fixture.globalRuntime.root,
203204
globalRuntime: fixture.globalRuntime,
204205
env: {}
205206
}

‎scripts/test-real-codex-host-probe.js‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const {
2929
isNonterminalH3SafePartial,
3030
isOwnedCleanupComplete,
3131
isPathInside,
32+
isPidAlive,
3233
normalizeObservedCommand,
3334
normalizeObservedCommandVariants,
3435
openAttemptLedger,
@@ -1886,6 +1887,16 @@ async function main() {
18861887
assert.strictEqual(timeoutChild.cleanup.attempted, true)
18871888
assert.match(timeoutChild.cleanup.method, /exact/)
18881889
assert.strictEqual(timeoutChild.cleanup.stillRunning, false)
1890+
assert.strictEqual(isPidAlive(4242, {
1891+
platform: 'linux',
1892+
fs: { readFileSync: () => '4242 (fixture worker) Z 1 2 3' },
1893+
kill: () => { throw Object.assign(new Error('must not probe a zombie'), { code: 'ESRCH' }) }
1894+
}), false)
1895+
assert.strictEqual(isPidAlive(4243, {
1896+
platform: 'linux',
1897+
fs: { readFileSync: () => '4243 (fixture worker) R 1 2 3' },
1898+
kill: () => undefined
1899+
}), true)
18891900
let boundedCleanupPid = null
18901901
const boundedCleanupChild = await runOwnedChild({
18911902
command: process.execPath,

0 commit comments

Comments
 (0)