write icon indicating copy to clipboard operation
write copied to clipboard

Possible race condition if 2 calls write to the same file

Open Soulike opened this issue 4 years ago • 0 comments

I think there is a race condition when 2 write() calls write to the same file at almost the same time, like the test case below:

const targetFile = path.join(os.tmpdir(), 'test.txt');

fs.rmSync(targetFile, {force: true});

const content1 = Buffer.alloc(100 * 1024 * 1024); // A will finish writing later than B
const content2 = Buffer.alloc(50 * 1024 * 1024);

crypto.randomFillSync(content1);
crypto.randomFillSync(content2);

process.on('uncaughtException', (e) =>
{
    console.error(e);
});

process.on('beforeExit', () =>
{
    fs.rmSync(targetFile, {force: true});
});

// A
write(targetFile, content1, {overwrite: true}, err =>
{
    if (err)
    {
        console.error(err);
    }
    else
    {
        const targetContent = fs.readFileSync(targetFile);
        assert.ok(targetContent.equals(content1), `The content of targetFile is not content1!`);
    }
});


// B
write(targetFile, content2, {overwrite: true}, err =>
{
    if (err)
    {
        console.error(err);
    }
    else
    {
        const targetContent = fs.readFileSync(targetFile);
        assert.ok(targetContent.equals(content2), `The content of targetFile is not content2!`);
    }
});

And the execution result is:

AssertionError [ERR_ASSERTION]: The content of targetFile is not content2!
...
AssertionError [ERR_ASSERTION]: The content of targetFile is not content1!
...

targetFile may become a corrupted file with content different from either content1 or content2.

I think the bug is caused by the use of stream:

https://github.com/jonschlinkert/write/blob/f537eb68091d0257b5a4ea915aa00a2c46727198/index.js#L58-L61

Both A and B can create write streams and write to targetFile at the same time. I think write() should check whether a file is being written before writing to it.

Soulike avatar Nov 26 '21 12:11 Soulike