AvianFlu / ncp

Asynchronous recursive file copying with Node.js.
MIT License
680 stars 103 forks source link

Race condition when 2 calls copying files to the same directory #142

Open Soulike opened 2 years ago

Soulike commented 2 years ago

The bug is similar to #141 but applies to files. Before copying a file, ncp first checks whether the target file exists. If it exists (writable is false), ncp will delete it and start copying.

https://github.com/AvianFlu/ncp/blob/6820b0fbe3f7400fdb283c741ef88b6d8e2d4994/lib/ncp.js#L221-L229

https://github.com/AvianFlu/ncp/blob/6820b0fbe3f7400fdb283c741ef88b6d8e2d4994/lib/ncp.js#L84-L97

So if 2 calls of ncp(), which copy files to the same directory, executes at almost the same time, the overwritten files in the target directory may be delete twice, and the latter one will throw error.

The test case below can reproduce the bug:

const sourceDir = '...dir path'
const tmpDir = path.join(os.tmpdir(), 'testFolder');

fs.rmSync(tmpDir, {recursive: true, force: true});
fs.mkdirSync(tmpDir);

ncp(sourceDir, tmpDir, function (err)
{
    if (err)
    {
        return console.error(err);
    }
    console.log('done!');

    ncp(sourceDir, tmpDir, function (err)
    {
        if (err)
        {
            return console.error(err);
        }
        console.log('done!');
    });

    ncp(sourceDir, tmpDir, function (err)
    {
        if (err)
        {
            return console.error(err);
        }
        console.log('done!');
    });
});

The execution result:

done!
[
   [Error: ENOENT: no such file or directory, unlink '/tmp/testFolder/xxxxx']
   [Error: ENOENT: no such file or directory, unlink '/tmp/testFolder/xxxxx']
    ...
]
done!