Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible race condition if 2 calls write to the same file #13

Open
Soulike opened this issue Nov 26, 2021 · 0 comments
Open

Possible race condition if 2 calls write to the same file #13

Soulike opened this issue Nov 26, 2021 · 0 comments

Comments

@Soulike
Copy link

Soulike commented Nov 26, 2021

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:

write/index.js

Lines 58 to 61 in f537eb6

fs.createWriteStream(destpath, opts)
.on('error', err => reject(err))
.on('close', resolve)
.end(ensureNewline(data, opts));

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant