|
| 1 | +'use strict'; |
| 2 | +const common = require('../common'); |
| 3 | +const assert = require('assert'); |
| 4 | +const child_process = require('child_process'); |
| 5 | + |
| 6 | +// Test that workers fail with meaningful error message |
| 7 | +// when their initialization fails. |
| 8 | + |
| 9 | +if (common.isWindows) { |
| 10 | + common.skip('ulimit does not work on Windows.'); |
| 11 | +} |
| 12 | + |
| 13 | +// A reasonably low fd count. An empty node process |
| 14 | +// creates around 30 fds for its internal purposes, |
| 15 | +// so making it too low will crash the process early, |
| 16 | +// making it too high will cause too much resource use. |
| 17 | +const OPENFILES = 128; |
| 18 | + |
| 19 | +// Double the open files - so that some workers fail for sure. |
| 20 | +const WORKERCOUNT = 256; |
| 21 | + |
| 22 | +if (process.argv[2] === 'child') { |
| 23 | + const { Worker } = require('worker_threads'); |
| 24 | + for (let i = 0; i < WORKERCOUNT; ++i) { |
| 25 | + const worker = new Worker( |
| 26 | + 'require(\'worker_threads\').parentPort.postMessage(2 + 2)', |
| 27 | + { eval: true }); |
| 28 | + worker.on('message', (result) => { |
| 29 | + assert.strictEqual(result, 4); |
| 30 | + }); |
| 31 | + |
| 32 | + // We want to test that if there is an error in a constrained running |
| 33 | + // environment, it will be one of `EMFILE` or `ERR_WORKER_INIT_FAILED`. |
| 34 | + // `common.mustCall*` cannot be used here as in some environments |
| 35 | + // (i.e. single cpu) `ulimit` may not lead to such an error. |
| 36 | + |
| 37 | + worker.on('error', (e) => { |
| 38 | + assert.match(e.message, /EMFILE/); |
| 39 | + assert.ok(e.code === 'ERR_WORKER_INIT_FAILED' || e.code === 'EMFILE'); |
| 40 | + }); |
| 41 | + } |
| 42 | + |
| 43 | +} else { |
| 44 | + // Limit the number of open files, to force workers to fail. |
| 45 | + let testCmd = `ulimit -n ${OPENFILES} && `; |
| 46 | + testCmd += `${process.execPath} ${__filename} child`; |
| 47 | + const cp = child_process.exec(testCmd); |
| 48 | + |
| 49 | + // Turn on the child streams for debugging purposes. |
| 50 | + let stdout = ''; |
| 51 | + cp.stdout.setEncoding('utf8'); |
| 52 | + cp.stdout.on('data', (chunk) => { |
| 53 | + stdout += chunk; |
| 54 | + }); |
| 55 | + let stderr = ''; |
| 56 | + cp.stderr.setEncoding('utf8'); |
| 57 | + cp.stderr.on('data', (chunk) => { |
| 58 | + stderr += chunk; |
| 59 | + }); |
| 60 | + |
| 61 | + cp.on('exit', common.mustCall((code, signal) => { |
| 62 | + console.log(`child stdout: ${stdout}\n`); |
| 63 | + console.log(`child stderr: ${stderr}\n`); |
| 64 | + assert.strictEqual(code, 0); |
| 65 | + assert.strictEqual(signal, null); |
| 66 | + })); |
| 67 | +} |
0 commit comments