11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ciconst common = require('../common'); 31cb0ef41Sopenharmony_ciconst assert = require('assert'); 41cb0ef41Sopenharmony_ciconst { Worker, isMainThread } = require('worker_threads'); 51cb0ef41Sopenharmony_ciconst { once } = require('events'); 61cb0ef41Sopenharmony_ciconst fs = require('fs'); 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ciif (!isMainThread) 91cb0ef41Sopenharmony_ci common.skip('test needs to be able to freely set `trackUnmanagedFds`'); 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ci// All the tests here are run sequentially, to avoid accidentally opening an fd 121cb0ef41Sopenharmony_ci// which another part of the test expects to be closed. 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ciconst preamble = ` 151cb0ef41Sopenharmony_ciconst fs = require("fs"); 161cb0ef41Sopenharmony_ciconst { parentPort } = require('worker_threads'); 171cb0ef41Sopenharmony_ciconst __filename = ${JSON.stringify(__filename)}; 181cb0ef41Sopenharmony_ciprocess.on('warning', (warning) => parentPort.postMessage({ warning })); 191cb0ef41Sopenharmony_ci`; 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci(async () => { 221cb0ef41Sopenharmony_ci // Consistency check: Without trackUnmanagedFds, FDs are *not* closed. 231cb0ef41Sopenharmony_ci { 241cb0ef41Sopenharmony_ci const w = new Worker(`${preamble} 251cb0ef41Sopenharmony_ci parentPort.postMessage(fs.openSync(__filename)); 261cb0ef41Sopenharmony_ci `, { eval: true, trackUnmanagedFds: false }); 271cb0ef41Sopenharmony_ci const [ [ fd ] ] = await Promise.all([once(w, 'message'), once(w, 'exit')]); 281cb0ef41Sopenharmony_ci assert(fd > 2); 291cb0ef41Sopenharmony_ci fs.fstatSync(fd); // Does not throw. 301cb0ef41Sopenharmony_ci fs.closeSync(fd); 311cb0ef41Sopenharmony_ci } 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci // With trackUnmanagedFds, FDs are closed automatically. 341cb0ef41Sopenharmony_ci { 351cb0ef41Sopenharmony_ci const w = new Worker(`${preamble} 361cb0ef41Sopenharmony_ci parentPort.postMessage(fs.openSync(__filename)); 371cb0ef41Sopenharmony_ci `, { eval: true, trackUnmanagedFds: true }); 381cb0ef41Sopenharmony_ci const [ [ fd ] ] = await Promise.all([once(w, 'message'), once(w, 'exit')]); 391cb0ef41Sopenharmony_ci assert(fd > 2); 401cb0ef41Sopenharmony_ci assert.throws(() => fs.fstatSync(fd), { code: 'EBADF' }); 411cb0ef41Sopenharmony_ci } 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci // The same, but trackUnmanagedFds is used only as the implied default. 441cb0ef41Sopenharmony_ci { 451cb0ef41Sopenharmony_ci const w = new Worker(`${preamble} 461cb0ef41Sopenharmony_ci parentPort.postMessage(fs.openSync(__filename)); 471cb0ef41Sopenharmony_ci `, { eval: true }); 481cb0ef41Sopenharmony_ci const [ [ fd ] ] = await Promise.all([once(w, 'message'), once(w, 'exit')]); 491cb0ef41Sopenharmony_ci assert(fd > 2); 501cb0ef41Sopenharmony_ci assert.throws(() => fs.fstatSync(fd), { code: 'EBADF' }); 511cb0ef41Sopenharmony_ci } 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci // There is a warning when an fd is unexpectedly opened twice. 541cb0ef41Sopenharmony_ci { 551cb0ef41Sopenharmony_ci const w = new Worker(`${preamble} 561cb0ef41Sopenharmony_ci parentPort.postMessage(fs.openSync(__filename)); 571cb0ef41Sopenharmony_ci parentPort.once('message', () => { 581cb0ef41Sopenharmony_ci const reopened = fs.openSync(__filename); 591cb0ef41Sopenharmony_ci fs.closeSync(reopened); 601cb0ef41Sopenharmony_ci }); 611cb0ef41Sopenharmony_ci `, { eval: true, trackUnmanagedFds: true }); 621cb0ef41Sopenharmony_ci const [ fd ] = await once(w, 'message'); 631cb0ef41Sopenharmony_ci fs.closeSync(fd); 641cb0ef41Sopenharmony_ci w.postMessage(''); 651cb0ef41Sopenharmony_ci const [ { warning } ] = await once(w, 'message'); 661cb0ef41Sopenharmony_ci assert.match(warning.message, 671cb0ef41Sopenharmony_ci /File descriptor \d+ opened in unmanaged mode twice/); 681cb0ef41Sopenharmony_ci } 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci // There is a warning when an fd is unexpectedly closed. 711cb0ef41Sopenharmony_ci { 721cb0ef41Sopenharmony_ci const w = new Worker(`${preamble} 731cb0ef41Sopenharmony_ci parentPort.once('message', (fd) => { 741cb0ef41Sopenharmony_ci fs.closeSync(fd); 751cb0ef41Sopenharmony_ci }); 761cb0ef41Sopenharmony_ci `, { eval: true, trackUnmanagedFds: true }); 771cb0ef41Sopenharmony_ci w.postMessage(fs.openSync(__filename)); 781cb0ef41Sopenharmony_ci const [ { warning } ] = await once(w, 'message'); 791cb0ef41Sopenharmony_ci assert.match(warning.message, 801cb0ef41Sopenharmony_ci /File descriptor \d+ closed but not opened in unmanaged mode/); 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci})().then(common.mustCall()); 83