Description
I'd like to re-open the discussion about ENOTEMPTY problems on Windows, as previously raised in #25.
Technical background: On Windows, a file can be "busy" when our process or another process still has an open file handle. This can happen unpredictably; e.g. a webserver might have an open connection serving the file, or a virus scanner might be accessing it. When you remove a busy file (with fs.unlinkSync
or fs.unlink
), unlinkSync
will return successfully, but the file sticks around on the file system until the handle is released. As a result, when rimraf removes a file and then tries to rmdir
the containing directory, the rmdir
operation can fail with ENOTEMPTY
. (This is from memory and hearsay, so some details may be wrong!)
This causes random sporadic failures - see e.g. the stack trace reported in broccolijs/broccoli#232.
There is currently a workaround implemented in rimraf (d819b12, fixing #25). However, it is based on retrying repeatedly with setTimeout
, and it only works in the asynchronous version. Of course, this seems pretty hackish and potentially unreliable. We're using rimraf a lot in the Broccoli plugin ecosystem, and it makes me worried that we'll have lots of issues on Windows down the line.
So I'd love it if we could find a proper fix for this issue, rather than working around it.
It surely must be possible to find a fix - and this is why I'm opening this issue again: For example, commands like rmdir /s
can't possibly be relying on weird workarounds, can they? And Windows Explorer lets you delete directories, without random (flickering) failures stemming from your virus scanner accessing some file.
More detail for people wishing to dig in: this gist by @stefanpenner; this comment in libuv's fs.c; libuv's unlink implementation on Windows. I wonder if libuv's very roundabout unlink implementation (presumably to mimic POSIX) might be a contributor. Could this be fixable in libuv, or could we come up with a platform-specific C implementation for rimraf on Windows that doesn't use libuv?