'use strict'; const common = require('../common'); const assert = require('assert'); const child_process = require('child_process'); const fs = require('fs'); const stream = require('stream'); if (!common.isLinux) { common.skip('The fs watch limit is OS-dependent'); } if (common.isPi) { common.skip('Too slow for Raspberry Pi devices'); } try { // Ensure inotify limit is low enough for the test to actually exercise the // limit with small enough resources. const limit = Number( fs.readFileSync('/proc/sys/fs/inotify/max_user_watches', 'utf8')); if (limit > 16384) common.skip('inotify limit is quite large'); } catch (e) { if (e.code === 'ENOENT') common.skip('the inotify /proc subsystem does not exist'); // Fail on other errors. throw e; } const processes = []; const gatherStderr = new stream.PassThrough(); gatherStderr.setEncoding('utf8'); gatherStderr.setMaxListeners(Infinity); let finished = false; function spawnProcesses() { for (let i = 0; i < 10; ++i) { const proc = child_process.spawn( process.execPath, [ '-e', `process.chdir(${JSON.stringify(__dirname)}); for (const file of fs.readdirSync('.')) fs.watch(file, () => {});`, ], { stdio: ['inherit', 'inherit', 'pipe'] }); proc.stderr.pipe(gatherStderr); processes.push(proc); } setTimeout(() => { if (!finished && processes.length < 200) spawnProcesses(); }, 100); } spawnProcesses(); let accumulated = ''; gatherStderr.on('data', common.mustCallAtLeast((chunk) => { accumulated += chunk; if (accumulated.includes('Error:') && !finished) { assert( accumulated.includes('ENOSPC: System limit for number ' + 'of file watchers reached') || accumulated.includes('EMFILE: '), accumulated); console.log(`done after ${processes.length} processes, cleaning up`); finished = true; processes.forEach((proc) => proc.kill()); } }, 1));