node/test/async-hooks/test-improper-unwind.js
Trivikram Kamat 771230df78
test: accept SIGILL aborts in async-hooks tests
Use common.nodeProcessAborted() for the intentional abort path so
platform-specific abort signals such as SIGILL are accepted.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: openai:gpt-5.5
PR-URL: https://github.com/nodejs/node/pull/63687
Refs: https://github.com/nodejs/reliability/blob/main/reports/2026-06-01.md#jstest-failure
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
2026-06-18 10:09:54 +02:00

74 lines
2.4 KiB
JavaScript

// Flags: --expose-internals
'use strict';
const common = require('../common');
const assert = require('assert');
const internal_async_hooks = require('internal/async_hooks');
const { spawn } = require('child_process');
const corruptedMsg = /async hook stack has become corrupted/;
const heartbeatMsg = /heartbeat: still alive/;
const {
newAsyncId, getDefaultTriggerAsyncId,
emitInit, emitBefore, emitAfter,
} = internal_async_hooks;
const initHooks = require('./init-hooks');
if (process.argv[2] === 'child') {
const hooks = initHooks();
hooks.enable();
// In both the below two cases 'before' of event2 is nested inside 'before'
// of event1.
// Therefore the 'after' of event2 needs to occur before the
// 'after' of event 1.
// The first test of the two below follows that rule,
// the second one doesn't.
const eventOneId = newAsyncId();
const eventTwoId = newAsyncId();
const triggerId = getDefaultTriggerAsyncId();
emitInit(eventOneId, 'event1', triggerId, {});
emitInit(eventTwoId, 'event2', triggerId, {});
// Proper unwind
emitBefore(eventOneId, triggerId);
emitBefore(eventTwoId, triggerId);
emitAfter(eventTwoId);
emitAfter(eventOneId);
// Improper unwind
emitBefore(eventOneId, triggerId);
emitBefore(eventTwoId, triggerId);
console.log('heartbeat: still alive');
emitAfter(eventOneId);
} else {
const args = ['--expose-internals']
.concat(process.argv.slice(1))
.concat('child');
let errData = Buffer.from('');
let outData = Buffer.from('');
const child = spawn(process.execPath, args);
child.stderr.on('data', (d) => { errData = Buffer.concat([ errData, d ]); });
child.stdout.on('data', (d) => { outData = Buffer.concat([ outData, d ]); });
child.on('close', common.mustCall((code, signal) => {
if ((common.isAIX ||
(common.isLinux && process.arch === 'x64')) &&
common.nodeProcessAborted(code, signal)) {
// XXX: The child process could be aborted due to unknown reasons. Work around it.
} else {
assert.strictEqual(signal, null);
assert.strictEqual(code, 1);
}
assert.match(outData.toString(), heartbeatMsg,
'did not crash until we reached offending line of code ' +
`(found ${outData})`);
assert.match(errData.toString(), corruptedMsg,
'printed error contains corrupted message ' +
`(found ${errData})`);
}));
}