Files
node/test/parallel/test-web-locks-no-livelock.js

52 lines
1.7 KiB
JavaScript

// Flags: --expose-internals
// Regression test for https://github.com/nodejs/node/issues/62644.
'use strict';
const common = require('../common');
if (!common.isDebug) {
common.skip('Only works in debug mode');
}
const assert = require('node:assert');
const { once } = require('node:events');
const {
isMainThread,
parentPort,
workerData,
Worker,
} = require('node:worker_threads');
const resource = `web-locks-no-livelock`;
if (!isMainThread) {
// A pending lock request alone does not keep the worker alive, so keep a
// message listener until the parent terminates this Environment.
parentPort.on('message', () => {});
navigator.locks.request(workerData, () => {});
parentPort.postMessage('ready');
} else {
const { internalBinding } = require('internal/test/binding');
const { getGenericUsageCount } = internalBinding('debug');
const wakeCounter = 'LockManager.WakeEnvironment';
(async () => {
let worker;
let pendingInMain;
await navigator.locks.request(resource, common.mustCall(async () => {
// The worker queues an exclusive request for the resource held above.
worker = new Worker(__filename, { workerData: resource });
await once(worker, 'message');
// Queueing a second blocked request must not wake the worker: its
// request cannot make progress, so the two Environments would wake
// each other forever (livelock).
const wakeCount = getGenericUsageCount(wakeCounter);
pendingInMain = navigator.locks.request(resource, common.mustCall());
assert.strictEqual(getGenericUsageCount(wakeCounter), wakeCount);
}));
await pendingInMain;
await worker.terminate();
})().then(common.mustCall());
}