Skip to content

Fix issue #49: Retry rmdirSync on Windows for up to 1 second if files still exist.#179

Merged
arturadib merged 4 commits intoshelljs:masterfrom
andreialecu:fix-rmrfwin32
Jun 5, 2015
Merged

Fix issue #49: Retry rmdirSync on Windows for up to 1 second if files still exist.#179
arturadib merged 4 commits intoshelljs:masterfrom
andreialecu:fix-rmrfwin32

Conversation

@andreialecu
Copy link
Contributor

See issue #49

@andreialecu
Copy link
Contributor Author

I have an idea on how to make a test for this using https://github.com/cjohansen/Sinon.JS by stubbing fs.rmdirSync to return that error on first call, and process.platform to return win32 but I don't know if you want to take a dependency for it. Thoughts?

@arturadib
Copy link
Collaborator

Looks good, I don't think we need to a specific platform test for this.. I need a second pair of eyes though - @Schoonology ?

@Schoonology
Copy link
Contributor

Looking over that issue again, I wouldn't retry on EPERM - getting that error is the best way to know you've got multiple processes contending for those files.

@Schoonology
Copy link
Contributor

I've left all the comments I can think of for now. Thoughts, rebuttals, etc.? Though this is a relatively small amount of code, I feel like rm is somewhat important to get right...

@andreialecu
Copy link
Contributor Author

@Schoonology I fixed the style issues you pointed out and re-pushed.

Regarding EPERM: It was one of the errors I was getting for which retry helped. For the EPERM case, it could be an antivirus related issue. I don't think 1 second of retrying is that much of a big deal if the file is actually in use, before the error is re-thrown.

Regarding checking for win32: on other plaforms the files should disappear even if they're in use, it's only Windows that locks files from being deleted under such circumstances. If an error occurs on Linux for instance, it's probably because of permissions, not because of quirks such as this one. (at least - I couldn't reproduce this error on Linux and MacOSX, it works fine there)

@andreialecu
Copy link
Contributor Author

There's one more issue here: In my usage, after doing a rm -rf, I'm recreating the same directory I deleted.

This sometimes results in an error in mkdir because the directory didn't disappear yet. There needs to be an additional check on Windows whether the directory is gone before returning from the function. There won't be any error in this case in rmdirSync and nothing logged, but it just takes one extra milisecond for the directory to actually disappear from the file system.

To reiterate, shelljs is being used as part of a test suite for a library I'm working on and this was the final fix to all of the shelljs related problems I was getting running this test suite of 100+ tests on Windows.

@andreialecu
Copy link
Contributor Author

@Schoonology need your input on https://github.com/arturadib/shelljs/pull/179/files#diff-d0eda960c284276e6b0b269826fec539R56

I thought this was the simplest, I don't think that line will ever throw on non-Windows, but if it ever does, I think it's a good thing. I assume the calling application would want to know an allegedly successful call to remove a directory somehow still left the directory behind. Thoughts?

src/rm.js Outdated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine, though since it's potentially user-facing, I'd like to invest a little more time in the thrown Error:

  1. Throw an actual Error. No base class needed.
  2. EEXIST is specific to creating files. Could we use a more generic error like EAGAIN or even EOTHER?
  3. A good message.

@arturadib - Do we have a precedent for these kinds of errors?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we use common.error() for error messages

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know what you want to do about it and I'll change it.

@Schoonology Regarding 1 and 2: I'm not sure how you would concatenate a good message with an actual Error without creating a new Error class. Could you clarify?

@arturadib The code flow goes to the outer catch which does use common.error(). That throw there is just to give it a chance to retry. It's handled by the inner catch in the if. If the error is re-thrown, the outer catch handles it normally.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andreialecu - I completely missed that outer catch. Thanks for being patient with me, and pointing that out. That solves 1 and 3, and I'd just replace 2 with EAGAIN, because trying again may succeed, whereas EEXIST is meant to indicate that creating a new file failed because one already exists, and the user should not try again until that's resolved.

Does that make sense?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @Schoonology, I changed it to EAGAIN. Check it out now.

@Schoonology
Copy link
Contributor

I'm good with this, and I think @arturadib's concerns are satisfied with that outer catch, just as you pointed out.

Squash it and :shipit:.

@waddlesplash
Copy link
Contributor

bump. It'd be nice if this could get merged, I'm running into it a lot on Windows...

arturadib added a commit that referenced this pull request Jun 5, 2015
Fix issue #49: Retry rmdirSync on Windows for up to 1 second if files still exist.
@arturadib arturadib merged commit 25f0cf0 into shelljs:master Jun 5, 2015
@arturadib
Copy link
Collaborator

changes published to version 0.5.1, thanks everyone!

@sparkleholic
Copy link

Coool ! 👍

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

Successfully merging this pull request may close these issues.

5 participants