node/test/parallel/test-worker-http2-stream-terminate.js
ywave620 7a37829ccb
src: fix cb scope bugs involved in termination
Be more aggresive to clean up the async id stack,
and ensure the cleanup when terminating.

Calling SetIdle() when terminating is not harmless.
When node terminates due to an unhandled exception,
v8 preseves the vm state, which is JS and notifies
node through PerIsolateMessageListener(). If node
calls SetIdle() later, v8 complains because it
requires the vm state to either be EXTERNEL or IDLE
when embedder calling SetIdle().

PR-URL: https://github.com/nodejs/node/pull/45596
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
2023-02-28 03:17:46 +00:00

64 lines
1.6 KiB
JavaScript

'use strict';
const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');
const assert = require('assert');
const http2 = require('http2');
const makeDuplexPair = require('../common/duplexpair');
const { parentPort, Worker } = require('worker_threads');
// This test ensures that workers can be terminated without error while
// stream activity is ongoing, in particular the C++ function
// ReportWritesToJSStreamListener::OnStreamAfterReqFinished.
const MAX_ITERATIONS = 5;
const MAX_THREADS = 6;
// Do not use isMainThread so that this test itself can be run inside a Worker.
if (!process.env.HAS_STARTED_WORKER) {
process.env.HAS_STARTED_WORKER = 1;
function spinWorker(iter) {
const w = new Worker(__filename);
w.on('message', common.mustCall((msg) => {
assert.strictEqual(msg, 'terminate');
w.terminate();
}));
w.on('exit', common.mustCall(() => {
if (iter < MAX_ITERATIONS)
spinWorker(++iter);
}));
}
for (let i = 0; i < MAX_THREADS; i++) {
spinWorker(0);
}
} else {
const server = http2.createServer();
let i = 0;
server.on('stream', (stream, headers) => {
if (i === 1) {
parentPort.postMessage('terminate');
}
i++;
stream.end('');
});
const { clientSide, serverSide } = makeDuplexPair();
server.emit('connection', serverSide);
const client = http2.connect('http://localhost:80', {
createConnection: () => clientSide,
});
function makeRequests() {
for (let i = 0; i < 3; i++) {
client.request().end();
}
setImmediate(makeRequests);
}
makeRequests();
}