fix(desktop): skip cold process probes for dead backend-ownership PIDs
Windows Get-Process and macOS ps exit 1 on a missing PID, so reapOrphans kept stale records and the next launch paid another 2-8s spawn each. Throw ESRCH from the existing isPidAlive helper before any shell-out. Closes #92875 Co-authored-by: Jackal991 <139240222+Jackal991@users.noreply.github.com> Co-authored-by: jonotonfoto <126111813+jonotonfoto@users.noreply.github.com> Co-authored-by: foras910521-lab <268267187+foras910521-lab@users.noreply.github.com>
This commit is contained in:
committed by
brooklyn!
parent
e22f8a7fbd
commit
a2907a8bcd
@@ -66,9 +66,15 @@ test('processStartMarker resolves a real marker for the current process', async
|
||||
assert.match(marker, /^(linux|win|winms|ps):.+/)
|
||||
})
|
||||
|
||||
test('processStartMarker rejects for a PID that does not exist', async () => {
|
||||
test('a missing PID is classified as ESRCH so reapOrphans can drop the record', async () => {
|
||||
// Largest PIDs are bounded well below this on every supported platform.
|
||||
await assert.rejects(processStartMarker(2 ** 30 + 12345))
|
||||
// Windows Get-Process / macOS `ps -p` used to surface exit code 1, which
|
||||
// the identity matchers treated as "unknown" and kept forever. The native
|
||||
// gate throws ESRCH — the errno those catch blocks already map to gone.
|
||||
await assert.rejects(
|
||||
processStartMarker(2 ** 30 + 12345),
|
||||
(error: NodeJS.ErrnoException) => error?.code === 'ESRCH'
|
||||
)
|
||||
})
|
||||
|
||||
// --- PID-only marker helpers --------------------------------------------------
|
||||
|
||||
@@ -21,6 +21,7 @@ import { execFile } from 'node:child_process'
|
||||
import fs from 'node:fs'
|
||||
|
||||
import { electronProcessStartMarker } from './parent-process-identity'
|
||||
import { isPidAlive } from './update-marker'
|
||||
import { hiddenWindowsChildOptions } from './windows-child-options'
|
||||
|
||||
export function execText(command: string, args: string[], { timeout = 3000 } = {}): Promise<string> {
|
||||
@@ -42,6 +43,15 @@ export function execText(command: string, args: string[], { timeout = 3000 } = {
|
||||
* `claimDecision` / `probeStartMarker`).
|
||||
*/
|
||||
export async function processStartMarker(pid: number): Promise<string> {
|
||||
// Cheap native dead-PID gate. Windows Get-Process / macOS `ps -p` exit 1
|
||||
// on a missing PID (not ESRCH), so the identity matchers used to keep the
|
||||
// orphan and re-probe it every launch (#92875). ESRCH is the code those
|
||||
// catch blocks already map to "gone". Alive or uninspectable (EPERM) PIDs
|
||||
// still fall through to the platform probe.
|
||||
if (!isPidAlive(pid)) {
|
||||
throw Object.assign(new Error(`PID ${pid} no longer exists`), { code: 'ESRCH' })
|
||||
}
|
||||
|
||||
if (process.platform === 'linux') {
|
||||
const stat = await fs.promises.readFile(`/proc/${pid}/stat`, 'utf8')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user