NodeJS sometimes fails to close a file after the read stream is destroyed

旧巷老猫 提交于 2019-12-25 03:44:35

问题


I'm trying to narrow down the cause of this issue and have run into some behaviour I didn't expect.

I'm running Node v11.8.0 on Ubuntu 18.04.1 LTS.

If I run this script:

const fs = require('fs');
const { promisify } = require('util');
const { spawn, spawnSync, execSync } = require('child_process');
const { O_RDWR } = fs.constants;

const pipePath = "/tmp/myPipe";

let pipeHandle;
let stream;

function pipeListener(data) {
    console.log("Pipe data received", data.length);
}

async function setupPipe() {
    await promisify(fs.unlink)(pipePath)
        .then(function() {}, function(err) {console.warn("Error removing pipe", err);}); // Ignore errors which may happen if the pipe doesn't exist

    spawnSync('mkfifo', [pipePath]);

    pipeHandle = await promisify(fs.open)(pipePath, O_RDWR); // https://stackoverflow.com/a/53492514/674675

    stream = fs.createReadStream(null, {fd: pipeHandle, autoClose: false});

    stream.on('data', pipeListener);
    stream.on('close', () => {/*console.log("Stream closed");*/});
    stream.once('data', () => {
        console.log("First data");
    });
}

async function teardownPipe() {
    stream.removeAllListeners('data');
    stream.close();
}

async function reproduceBug() {
    let i = 0;
    while(i < 50) {
        try {
            let stat = fs.fstatSync(pipeHandle);
            let path = fs.readlinkSync('/proc/self/fd/' + pipeHandle);
            console.warn("File", path, "still open after iteration", i);
        } catch (ex) {
        }
        i++;
        await setupPipe();
        await teardownPipe();
    }
    setInterval(() => {
        // Prevents the process from terminating so that you can inspect the handles with lsof
    }, 1000);
}

reproduceBug().then(() => {
    console.log("Done");
}, (err) => {
    console.error(err);
});

I would expect to see consistent results from each iteration of the loop.

But instead, I'm seeing inconsistent and unpredictable results:

josh@desktop-01:~$ node ./pipeMre.js
File /tmp/myPipe still open after iteration 9
File /tmp/myPipe still open after iteration 13
File /tmp/myPipe still open after iteration 14
File /tmp/myPipe still open after iteration 27
Done
josh@desktop-01:~$ node ./pipeMre.js
File /tmp/myPipe still open after iteration 7
File /tmp/myPipe still open after iteration 11
File /tmp/myPipe still open after iteration 14
Done
^C
josh@desktop-01:~$ node ./pipeMre.js
File /tmp/myPipe still open after iteration 8
File /tmp/myPipe still open after iteration 29
File /tmp/myPipe still open after iteration 43
File /tmp/myPipe still open after iteration 46
Done
^C
josh@desktop-01:~$ node ./pipeMre.js
File /tmp/myPipe still open after iteration 6
File /tmp/myPipe still open after iteration 7
File /tmp/myPipe still open after iteration 21
File /tmp/myPipe still open after iteration 40
File /tmp/myPipe still open after iteration 48
Done

Is this meant to happen? Why is the file descriptor sometimes closed and other times not? In my full application some of the file descriptors stay open until the process is terminated, which I'm having trouble reproducing in my minimal example.

来源:https://stackoverflow.com/questions/54662620/nodejs-sometimes-fails-to-close-a-file-after-the-read-stream-is-destroyed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!