-
-
Notifications
You must be signed in to change notification settings - Fork 148
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
Improved workarounds for win32 #119
Conversation
polyfills.js
Outdated
fs.stat(from, function (fromStater, fromSt) { | ||
if (!fromSt && toSt) { | ||
if (cb) cb(toStater ? er : null) | ||
} else if (fromSt && toSt && fromSt.size === toSt.size) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really fond about this, so could use some feedback/input on how it could be solved differently.
polyfills.js
Outdated
throw e | ||
} | ||
// Wait until destination exists and source no longer exists or that we've reached the backoff limit | ||
while ((fs.existsSync(from) || !fs.existsSync(to)) && Date.now() < backoffUntil) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possibly the worst hack ever, but it seems to be the only real way to solve inconsistent behavior on Windows where the destination and source can exist at the same time.
testing this out on a windows machine lead to crash: "error": "TypeError: Cannot read property 'size' of undefined", "errorStackTrace": "TypeError: Cannot read property 'size' of undefined\n at node_modules\graceful-fs\polyfills.js:112:45\n at node_modules\graceful-fs\polyfills.js:331:29\n at FSReqWrap.oncomplete (fs.js:114:15)" taking a quick look -- perhaps there needs to be error handling on the first call to fs.stat? Node v7.9.0 |
@conceptualspace I've added some additional sanity checks that should solve your crash. Thanks for testing and reporting the issue! |
that would be fine if node actually reported an EEXIST error, but it does not on windows -- we just get EACCS/EPERM if the destination already exists |
win 10x64 |
This only happens for directories and if you do the same on Linux/OSX you'll see it works just fine since the native rename in Linux will overwrite an existing target no matter what. So if we want to normalize this behavior, we should probably check for an existing target and unlink it if it exists.
|
The current polyfill will get stuck on Windows at renaming a directory when the target already exists. I think that we should make sure it works the same on both platform (i.e. remove the target directory if it exists). I tested using the following code: https://gist.github.com/mekwall/b6c44c6855aa9adbd97af1bba9386e50 |
The last commit normalizes the behavior. This is what I get with the test code from my gist linked above. Windows:
Linux:
|
I was playing around the EPERM issue during the day and it's now clear that the issue's cause is indeed in the resource locking as was written above by @mekwall. This is the way I've got it proven for myself:
const fd = await promisify(fs.open)(this.file, "r+");
setTimeout(async () => {
await promisify(fs.close)(fd);
}, 20 * 1000);
So backoff retry scenario should be really helpful, following the @mekwall 's idea. Antiviruses, Dropbox syncing and such kind of software apparently open files for a long time and very frequently, that's why there are so many EPERM issues posted on Github (which usually go to the close state without the actual resolution). So if there is no |
This is the test case I mentioned above https://github.com/vladimiry/fs-no-eperm-anymore/tree/master/src/test/locking - locked |
@isaacs do you think you could please take a look? |
What's the latest on this PR? It would be great to get this in to fix the issues we are seeing with the latest versions of Jest on Windows |
I encounter the EPERM issues very frequently still as do my colleagues. A colleague recently got a new workstation with windows 10, and could not do npm install with any version of npm he tried. He got the closest with npm 4.2.0. We tried blowing out the graceful-fs dependency used by npm in his installation with the files from this pull request, which fixed his issues. I hope this fix becomes a part of npm soon. Thank you for fixing it |
Thanks @mekwall for writing this patch! I work on TypeScript, Visual Studio, and Visual Studio Code. The underlying problem described here is coming up a lot for VS developers because the TypeScript language service puts a file watcher on the project folder (including when the user is just writing JavaScript). We typically see errors like this:
As the PR describes, this is definitely related to file watchers - in my testing, if we disable the file watching from the TSLS side, the error stops happening. I've done some testing and this PR definitely fixes the issue. The particular scenario we're trying to make work has gone from failing 1 in 4 times to succeeding the last 35 times in a row. We really need this to be merged - it's impacting a lot of developers and there's nothing that can be done on our end. Developers running |
Thank you, thank you, thank you, thank you, thank yo----- It may take longer to run a big |
NPM team really needs to merge this PR ASAP, could any guys in their team give a response? |
Hi. It seems like there's a semantic change here. If the target directory is not empty, then it should fail with Also, I'm not sure it's a good idea to spin on CPU for potentially 60 seconds in this case. Is it possible to make this time shorter, or allow it to be configured? |
Sadly I don't have time to fix this at the moment. Any takers? |
Closing this in favor of #131. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Y
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Y
Summary
This PR improves on the existing override for
fs.rename
and also adds a similar but blocking override forfs.renameSync
(obsoleting #23). The overrides tries to normalize the behavior offs.rename
andfs.renameSync
between platforms. It does this by ensuring that the file was actually moved before resolving within a 60 second time frame.Background
fs.rename
andfs.renameSync
uses MoveFileEx function on Windows. It is not an atomic operation and honors the Windows sharing modes, meaning that whenever a file or parent directory is locked (in use) the rename might fail with EACCS or EPERM errors depending on the sharing mode set on the file and/or directory.This differs from how the api call used by Linux and OSX works where the rename operation is atomic and will go through no matter if the file is locked or not.
Disabling anti-virus is NOT a viable solution
Most active anti-virus file scanners will lock the file and/or directory during scan, so if you are trying to rename it during this time you'll get an EPERM/EACCS error thrown in your face. Just to be clear: Disabling AV is NOT a viable solution and should never be accepted as such.
Issues possibly affected by this
npm install purecss
Fails on windows 10 pure-css/pure#647References