Skip to content

Commit d4492d9

Browse files
committed
test: harden test-process-exit-background-gc
The test only hung on an unfixed build about a third of the time, because the window in which the main thread is out of JS depended on how fast the machine runs pbkdf2, and the stress allocation task had to run into the heap limit inside that window. Calibrate the iteration count from a short probe so that the window is about a second everywhere, and use up the old generation budget just before exiting so that the next background allocation fails and parks the task. Run in the test process instead of spawning a child, which also drops the child process overhead. On an unfixed build the test now hangs in 20 of 20 runs, and it passes 30 of 30 with the fix. Signed-off-by: Manzoor Wani <manzoorwani.jk@gmail.com>
1 parent 4adeaab commit d4492d9

1 file changed

Lines changed: 24 additions & 22 deletions

File tree

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,32 @@
1+
// Flags: --stress-concurrent-allocation
12
'use strict';
23
const common = require('../common');
34
if (!common.hasCrypto) { common.skip('missing crypto'); }
45

56
// Regression test for https://github.com/nodejs/node/issues/64274.
6-
// process.exit() joins the V8 platform worker threads without tearing down
7-
// the isolate, so a background task waiting for a main thread GC hung it.
7+
// process.exit() joined the V8 platform workers while one was parked
8+
// waiting for a GC that the main thread no longer performs.
89

9-
const { spawnSyncAndExitWithoutError } = require('../common/child_process');
10+
const { pbkdf2, pbkdf2Sync } = require('crypto');
1011

11-
if (process.argv[2] === 'child') {
12-
const keep = [];
13-
for (let i = 0; i < 1e5; i++) keep.push({ i });
14-
setTimeout(() => {
15-
// uv_library_shutdown() waits for this job, keeping the main thread out
16-
// of JS while the stress task runs into the heap limit and waits for GC.
17-
require('crypto').pbkdf2('a', 'b', 5e6, 64, 'sha512', () => {});
18-
process.exit(0);
19-
}, 300);
20-
return;
21-
}
12+
// A small live set keeps the old generation limit low.
13+
const keep = [];
14+
for (let i = 0; i < 1e5; i++) keep.push({ i });
2215

23-
spawnSyncAndExitWithoutError(process.execPath, [
24-
'--stress-concurrent-allocation',
25-
__filename,
26-
'child',
27-
], {
28-
timeout: common.platformTimeout(30_000),
29-
killSignal: 'SIGKILL',
30-
});
16+
// Pick an iteration count that keeps the threadpool busy for about a second.
17+
const probeIterations = 2e5;
18+
const start = process.hrtime.bigint();
19+
pbkdf2Sync('a', 'b', probeIterations, 64, 'sha512');
20+
const nsPerIteration = Number(process.hrtime.bigint() - start) /
21+
probeIterations;
22+
const iterations = Math.ceil(1e9 / nsPerIteration);
23+
24+
setTimeout(() => {
25+
// uv_library_shutdown() waits for this job, so the main thread stays out of
26+
// JS and cannot serve the GC that the stress allocation task asks for.
27+
pbkdf2('a', 'b', iterations, 64, 'sha512', () => {});
28+
// Use up the old generation budget, so that the next background allocation
29+
// fails and parks that task in CollectionBarrier.
30+
for (let i = 0; i < 40; i++) new Array(1e5).fill(i);
31+
process.exit(0);
32+
}, 300);

0 commit comments

Comments
 (0)