test(desktop): no-console-git fixture publishes its pid file atomically

The hanging-tree fixture's grandchild wrote pids.json with a plain
writeFileSync (open+truncate, then write) while the test polls
existsSync -> JSON.parse. A read landing between the truncate and the write
sees an empty file and throws "Unexpected end of JSON input" in port() or in
the cleanup, failing "app quit kills a timed git command ..." at random
(seen on PR #129573, whose diff touches no electron file).

Write to <file>.tmp and rename: rename is atomic on POSIX and Windows, so
existence now implies complete content for every reader.

Probe (same writer/reader shapes, separate processes, 300 runs each):
plain writeFileSync 12/300 torn reads, tmp+rename 0/300.

Regression from 4daeec7f2c (#127983), which rewrote the fixture around the
unsafe existsSync->parse read that c42db5415f introduced.
This commit is contained in:
kshitijk4poor
2026-10-01 01:32:59 +05:30
committed by kshitij
parent 09681e7959
commit 02de0fa40f

View File

@@ -33,8 +33,11 @@ function hangingTreeFixture() {
const { spawn } = require('node:child_process');
const worker = String.raw\`const fs = require('node:fs');
const server = require('node:net').createServer(socket => socket.end());
server.listen(0, '127.0.0.1', () => fs.writeFileSync(process.argv[1],
JSON.stringify({ pids: [Number(process.argv[2]), process.pid], port: server.address().port })));\`;
server.listen(0, '127.0.0.1', () => {
fs.writeFileSync(process.argv[1] + '.tmp',
JSON.stringify({ pids: [Number(process.argv[2]), process.pid], port: server.address().port }));
fs.renameSync(process.argv[1] + '.tmp', process.argv[1]);
});\`;
spawn(process.execPath, ['-e', worker, process.argv[2], String(process.pid)], { stdio: 'inherit' });
setInterval(() => {}, 1000);
`