1'use strict'; 2const common = require('../common'); 3const assert = require('assert'); 4const child_process = require('child_process'); 5const fs = require('fs'); 6const stream = require('stream'); 7 8if (!common.isLinux) 9 common.skip('The fs watch limit is OS-dependent'); 10if (!common.enoughTestCpu) 11 common.skip('This test is resource-intensive'); 12 13try { 14 // Ensure inotify limit is low enough for the test to actually exercise the 15 // limit with small enough resources. 16 const limit = Number( 17 fs.readFileSync('/proc/sys/fs/inotify/max_user_watches', 'utf8')); 18 if (limit > 16384) 19 common.skip('inotify limit is quite large'); 20} catch (e) { 21 if (e.code === 'ENOENT') 22 common.skip('the inotify /proc subsystem does not exist'); 23 // Fail on other errors. 24 throw e; 25} 26 27const processes = []; 28const gatherStderr = new stream.PassThrough(); 29gatherStderr.setEncoding('utf8'); 30gatherStderr.setMaxListeners(Infinity); 31 32let finished = false; 33function spawnProcesses() { 34 for (let i = 0; i < 10; ++i) { 35 const proc = child_process.spawn( 36 process.execPath, 37 [ '-e', 38 `process.chdir(${JSON.stringify(__dirname)}); 39 for (const file of fs.readdirSync('.')) 40 fs.watch(file, () => {});`, 41 ], { stdio: ['inherit', 'inherit', 'pipe'] }); 42 proc.stderr.pipe(gatherStderr); 43 processes.push(proc); 44 } 45 46 setTimeout(() => { 47 if (!finished && processes.length < 200) 48 spawnProcesses(); 49 }, 100); 50} 51 52spawnProcesses(); 53 54let accumulated = ''; 55gatherStderr.on('data', common.mustCallAtLeast((chunk) => { 56 accumulated += chunk; 57 if (accumulated.includes('Error:') && !finished) { 58 assert( 59 accumulated.includes('ENOSPC: System limit for number ' + 60 'of file watchers reached') || 61 accumulated.includes('EMFILE: '), 62 accumulated); 63 console.log(`done after ${processes.length} processes, cleaning up`); 64 finished = true; 65 processes.forEach((proc) => proc.kill()); 66 } 67}, 1)); 68