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