Skip to content

Commit

Permalink
test: add Worker initialization failure test case
Browse files Browse the repository at this point in the history
Cover the scenario fixed through
#31621
Unfortunately there is no easy way to test this, in a
cross-platform manner. So the approach is:
 - open a child process with ulimit restriction on file descriptors
 - in the child process, start few workers - more than the fd limit
 - make sure some workers fail, with the expected error type.
 - skip the test in windows, as there is no ulimit there.

Refs: #31621

PR-URL: #31929
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
  • Loading branch information
HarshithaKP authored and addaleax committed Apr 5, 2020
1 parent 0ddfd0f commit 5b899d6
Showing 1 changed file with 67 additions and 0 deletions.
67 changes: 67 additions & 0 deletions test/parallel/test-worker-init-failure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const child_process = require('child_process');

// Test that workers fail with meaningful error message
// when their initialization fails.

if (common.isWindows) {
common.skip('ulimit does not work on Windows.');
}

// A reasonably low fd count. An empty node process
// creates around 30 fds for its internal purposes,
// so making it too low will crash the process early,
// making it too high will cause too much resource use.
const OPENFILES = 128;

// Double the open files - so that some workers fail for sure.
const WORKERCOUNT = 256;

if (process.argv[2] === 'child') {
const { Worker } = require('worker_threads');
for (let i = 0; i < WORKERCOUNT; ++i) {
const worker = new Worker(
'require(\'worker_threads\').parentPort.postMessage(2 + 2)',
{ eval: true });
worker.on('message', (result) => {
assert.strictEqual(result, 4);
});

// We want to test that if there is an error in a constrained running
// environment, it will be one of `EMFILE` or `ERR_WORKER_INIT_FAILED`.
// `common.mustCall*` cannot be used here as in some environments
// (i.e. single cpu) `ulimit` may not lead to such an error.

worker.on('error', (e) => {
assert.match(e.message, /EMFILE/);
assert.ok(e.code === 'ERR_WORKER_INIT_FAILED' || e.code === 'EMFILE');
});
}

} else {
// Limit the number of open files, to force workers to fail.
let testCmd = `ulimit -n ${OPENFILES} && `;
testCmd += `${process.execPath} ${__filename} child`;
const cp = child_process.exec(testCmd);

// Turn on the child streams for debugging purposes.
let stdout = '';
cp.stdout.setEncoding('utf8');
cp.stdout.on('data', (chunk) => {
stdout += chunk;
});
let stderr = '';
cp.stderr.setEncoding('utf8');
cp.stderr.on('data', (chunk) => {
stderr += chunk;
});

cp.on('exit', common.mustCall((code, signal) => {
console.log(`child stdout: ${stdout}\n`);
console.log(`child stderr: ${stderr}\n`);
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
}));
}

0 comments on commit 5b899d6

Please sign in to comment.