1'use strict'; 2const common = require('../common'); 3const assert = require('assert'); 4const { Worker, isMainThread } = require('worker_threads'); 5const { once } = require('events'); 6const fs = require('fs'); 7 8if (!isMainThread) 9 common.skip('test needs to be able to freely set `trackUnmanagedFds`'); 10 11// All the tests here are run sequentially, to avoid accidentally opening an fd 12// which another part of the test expects to be closed. 13 14const preamble = ` 15const fs = require("fs"); 16const { parentPort } = require('worker_threads'); 17const __filename = ${JSON.stringify(__filename)}; 18process.on('warning', (warning) => parentPort.postMessage({ warning })); 19`; 20 21(async () => { 22 // Consistency check: Without trackUnmanagedFds, FDs are *not* closed. 23 { 24 const w = new Worker(`${preamble} 25 parentPort.postMessage(fs.openSync(__filename)); 26 `, { eval: true, trackUnmanagedFds: false }); 27 const [ [ fd ] ] = await Promise.all([once(w, 'message'), once(w, 'exit')]); 28 assert(fd > 2); 29 fs.fstatSync(fd); // Does not throw. 30 fs.closeSync(fd); 31 } 32 33 // With trackUnmanagedFds, FDs are closed automatically. 34 { 35 const w = new Worker(`${preamble} 36 parentPort.postMessage(fs.openSync(__filename)); 37 `, { eval: true, trackUnmanagedFds: true }); 38 const [ [ fd ] ] = await Promise.all([once(w, 'message'), once(w, 'exit')]); 39 assert(fd > 2); 40 assert.throws(() => fs.fstatSync(fd), { code: 'EBADF' }); 41 } 42 43 // The same, but trackUnmanagedFds is used only as the implied default. 44 { 45 const w = new Worker(`${preamble} 46 parentPort.postMessage(fs.openSync(__filename)); 47 `, { eval: true }); 48 const [ [ fd ] ] = await Promise.all([once(w, 'message'), once(w, 'exit')]); 49 assert(fd > 2); 50 assert.throws(() => fs.fstatSync(fd), { code: 'EBADF' }); 51 } 52 53 // There is a warning when an fd is unexpectedly opened twice. 54 { 55 const w = new Worker(`${preamble} 56 parentPort.postMessage(fs.openSync(__filename)); 57 parentPort.once('message', () => { 58 const reopened = fs.openSync(__filename); 59 fs.closeSync(reopened); 60 }); 61 `, { eval: true, trackUnmanagedFds: true }); 62 const [ fd ] = await once(w, 'message'); 63 fs.closeSync(fd); 64 w.postMessage(''); 65 const [ { warning } ] = await once(w, 'message'); 66 assert.match(warning.message, 67 /File descriptor \d+ opened in unmanaged mode twice/); 68 } 69 70 // There is a warning when an fd is unexpectedly closed. 71 { 72 const w = new Worker(`${preamble} 73 parentPort.once('message', (fd) => { 74 fs.closeSync(fd); 75 }); 76 `, { eval: true, trackUnmanagedFds: true }); 77 w.postMessage(fs.openSync(__filename)); 78 const [ { warning } ] = await once(w, 'message'); 79 assert.match(warning.message, 80 /File descriptor \d+ closed but not opened in unmanaged mode/); 81 } 82})().then(common.mustCall()); 83