@@ -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+
15271552function 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,
0 commit comments