11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ciconst common = require('../common'); 31cb0ef41Sopenharmony_ciconst assert = require('assert'); 41cb0ef41Sopenharmony_ciconst child_process = require('child_process'); 51cb0ef41Sopenharmony_ci 61cb0ef41Sopenharmony_ci// Test that workers fail with meaningful error message 71cb0ef41Sopenharmony_ci// when their initialization fails. 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ciif (common.isWindows) { 101cb0ef41Sopenharmony_ci common.skip('ulimit does not work on Windows.'); 111cb0ef41Sopenharmony_ci} 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ciif (process.config.variables.node_builtin_modules_path) { 141cb0ef41Sopenharmony_ci common.skip('this test cannot pass when Node.js is built with --node-builtin-modules-path'); 151cb0ef41Sopenharmony_ci} 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_ci// A reasonably low fd count. An empty node process 181cb0ef41Sopenharmony_ci// creates around 30 fds for its internal purposes, 191cb0ef41Sopenharmony_ci// so making it too low will crash the process early, 201cb0ef41Sopenharmony_ci// making it too high will cause too much resource use. 211cb0ef41Sopenharmony_ciconst OPENFILES = 128; 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ci// Double the open files - so that some workers fail for sure. 241cb0ef41Sopenharmony_ciconst WORKERCOUNT = 256; 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ciif (process.argv[2] === 'child') { 271cb0ef41Sopenharmony_ci const { Worker } = require('worker_threads'); 281cb0ef41Sopenharmony_ci for (let i = 0; i < WORKERCOUNT; ++i) { 291cb0ef41Sopenharmony_ci const worker = new Worker( 301cb0ef41Sopenharmony_ci 'require(\'worker_threads\').parentPort.postMessage(2 + 2)', 311cb0ef41Sopenharmony_ci { eval: true }); 321cb0ef41Sopenharmony_ci worker.on('message', (result) => { 331cb0ef41Sopenharmony_ci assert.strictEqual(result, 4); 341cb0ef41Sopenharmony_ci }); 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci // We want to test that if there is an error in a constrained running 371cb0ef41Sopenharmony_ci // environment, it will be one of `ENFILE`, `EMFILE`, 'ENOENT', or 381cb0ef41Sopenharmony_ci // `ERR_WORKER_INIT_FAILED`. 391cb0ef41Sopenharmony_ci const expected = ['ERR_WORKER_INIT_FAILED', 'EMFILE', 'ENFILE', 'ENOENT']; 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci // `common.mustCall*` cannot be used here as in some environments 421cb0ef41Sopenharmony_ci // (i.e. single cpu) `ulimit` may not lead to such an error. 431cb0ef41Sopenharmony_ci worker.on('error', (e) => { 441cb0ef41Sopenharmony_ci assert.ok(expected.includes(e.code), `${e.code} not expected`); 451cb0ef41Sopenharmony_ci }); 461cb0ef41Sopenharmony_ci } 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci} else { 491cb0ef41Sopenharmony_ci // Limit the number of open files, to force workers to fail. 501cb0ef41Sopenharmony_ci let testCmd = `ulimit -n ${OPENFILES} && `; 511cb0ef41Sopenharmony_ci testCmd += `${process.execPath} ${__filename} child`; 521cb0ef41Sopenharmony_ci const cp = child_process.exec(testCmd); 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci // Turn on the child streams for debugging purposes. 551cb0ef41Sopenharmony_ci let stdout = ''; 561cb0ef41Sopenharmony_ci cp.stdout.setEncoding('utf8'); 571cb0ef41Sopenharmony_ci cp.stdout.on('data', (chunk) => { 581cb0ef41Sopenharmony_ci stdout += chunk; 591cb0ef41Sopenharmony_ci }); 601cb0ef41Sopenharmony_ci let stderr = ''; 611cb0ef41Sopenharmony_ci cp.stderr.setEncoding('utf8'); 621cb0ef41Sopenharmony_ci cp.stderr.on('data', (chunk) => { 631cb0ef41Sopenharmony_ci stderr += chunk; 641cb0ef41Sopenharmony_ci }); 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci cp.on('exit', common.mustCall((code, signal) => { 671cb0ef41Sopenharmony_ci console.log(`child stdout: ${stdout}\n`); 681cb0ef41Sopenharmony_ci console.log(`child stderr: ${stderr}\n`); 691cb0ef41Sopenharmony_ci assert.strictEqual(code, 0); 701cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 711cb0ef41Sopenharmony_ci })); 721cb0ef41Sopenharmony_ci} 73