11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ciconst common = require('../common'); 31cb0ef41Sopenharmony_ciconst assert = require('assert'); 41cb0ef41Sopenharmony_ciconst child_process = require('child_process'); 51cb0ef41Sopenharmony_ciconst fs = require('fs'); 61cb0ef41Sopenharmony_ciconst stream = require('stream'); 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ciif (!common.isLinux) { 91cb0ef41Sopenharmony_ci common.skip('The fs watch limit is OS-dependent'); 101cb0ef41Sopenharmony_ci} 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ciif (common.isPi) { 131cb0ef41Sopenharmony_ci common.skip('Too slow for Raspberry Pi devices'); 141cb0ef41Sopenharmony_ci} 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_citry { 171cb0ef41Sopenharmony_ci // Ensure inotify limit is low enough for the test to actually exercise the 181cb0ef41Sopenharmony_ci // limit with small enough resources. 191cb0ef41Sopenharmony_ci const limit = Number( 201cb0ef41Sopenharmony_ci fs.readFileSync('/proc/sys/fs/inotify/max_user_watches', 'utf8')); 211cb0ef41Sopenharmony_ci if (limit > 16384) 221cb0ef41Sopenharmony_ci common.skip('inotify limit is quite large'); 231cb0ef41Sopenharmony_ci} catch (e) { 241cb0ef41Sopenharmony_ci if (e.code === 'ENOENT') 251cb0ef41Sopenharmony_ci common.skip('the inotify /proc subsystem does not exist'); 261cb0ef41Sopenharmony_ci // Fail on other errors. 271cb0ef41Sopenharmony_ci throw e; 281cb0ef41Sopenharmony_ci} 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ciconst processes = []; 311cb0ef41Sopenharmony_ciconst gatherStderr = new stream.PassThrough(); 321cb0ef41Sopenharmony_cigatherStderr.setEncoding('utf8'); 331cb0ef41Sopenharmony_cigatherStderr.setMaxListeners(Infinity); 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_cilet finished = false; 361cb0ef41Sopenharmony_cifunction spawnProcesses() { 371cb0ef41Sopenharmony_ci for (let i = 0; i < 10; ++i) { 381cb0ef41Sopenharmony_ci const proc = child_process.spawn( 391cb0ef41Sopenharmony_ci process.execPath, 401cb0ef41Sopenharmony_ci [ '-e', 411cb0ef41Sopenharmony_ci `process.chdir(${JSON.stringify(__dirname)}); 421cb0ef41Sopenharmony_ci for (const file of fs.readdirSync('.')) 431cb0ef41Sopenharmony_ci fs.watch(file, () => {});`, 441cb0ef41Sopenharmony_ci ], { stdio: ['inherit', 'inherit', 'pipe'] }); 451cb0ef41Sopenharmony_ci proc.stderr.pipe(gatherStderr); 461cb0ef41Sopenharmony_ci processes.push(proc); 471cb0ef41Sopenharmony_ci } 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci setTimeout(() => { 501cb0ef41Sopenharmony_ci if (!finished && processes.length < 200) 511cb0ef41Sopenharmony_ci spawnProcesses(); 521cb0ef41Sopenharmony_ci }, 100); 531cb0ef41Sopenharmony_ci} 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_cispawnProcesses(); 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_cilet accumulated = ''; 581cb0ef41Sopenharmony_cigatherStderr.on('data', common.mustCallAtLeast((chunk) => { 591cb0ef41Sopenharmony_ci accumulated += chunk; 601cb0ef41Sopenharmony_ci if (accumulated.includes('Error:') && !finished) { 611cb0ef41Sopenharmony_ci assert( 621cb0ef41Sopenharmony_ci accumulated.includes('ENOSPC: System limit for number ' + 631cb0ef41Sopenharmony_ci 'of file watchers reached') || 641cb0ef41Sopenharmony_ci accumulated.includes('EMFILE: '), 651cb0ef41Sopenharmony_ci accumulated); 661cb0ef41Sopenharmony_ci console.log(`done after ${processes.length} processes, cleaning up`); 671cb0ef41Sopenharmony_ci finished = true; 681cb0ef41Sopenharmony_ci processes.forEach((proc) => proc.kill()); 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci}, 1)); 71