• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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