-
Notifications
You must be signed in to change notification settings - Fork 322
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
windows - wait to file to unlock for removal #10629
base: main
Are you sure you want to change the base?
Conversation
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.
If we're going to do it, I think we should do this in an async version of the function, and add some timeouts while this is going on.
That was my other solution, but it felt bigger change as I saw we have a Lines 17 to 39 in c1a0e38
So I was going to use that, but I went the other way |
You're probably right that the change is too big. It's not a problem for sync functions to become async, but it's indeed annoying. Do you have a reproducible example where this fixes the problem? Just to see the impact, could you
|
Yes I had one today that allowed me to drive this solution. I'll rerun it but I remember it was something ~50, other time ~70 and sometimes more than 100. I'll add the performance: thanks for the trick - I did not know about this JS code. |
while removing dir or file, it happens that EBUSY error could happen with file being used and lock. This is a simple way to wait for file to be unlocked, with a fail safe of max try to avoid infinite loop.
76ce3ca
to
927b920
Compare
I did 10 try to see number we get Number of attempts to remove / total duration
So it is pretty quick, and we are talking about some ms delay between Deno trying to remove and file being locked as OS busy on it. Does it help you assess the impact ? |
It does. ~50ms is not that fast, though. I'd hate to add a 50ms wait at every call to safeRemove. Do you have a sense of how often this happens? I'm now a bit more inclined to make this call async, so that we have a chance to (eventually) hide this latency in the rest of Quarto's processing. If we made this call async, then we could have a timeout instead of max number of tries. (the algorithm would be: pause for 10ms, try again, and give up after, say, 100ms). |
On the project I manage to make a reproducible example, It happens at every render to try clean the I wonder why this happens. I'll do some more testing, but maybe this is only happening to because I am running dev quarto while the source code is also open in VSCODE, which does a bunch of scanning of all the folders. I'll investigate this route, because maybe I scope the fix more, or even push my research with some VSCODE tweaks config instead. Anyhow, I am not in a hurry - I can leave with it, though I get some failed rendering quite often in this scenario.
For the give up part, just so it's clear, currently it will make the whole quarto render fails because Deno return an error while not being able to remove this empty directory. |
In that case, though, this would need to be an option. We don't want a timeout to silently fail to remove a file by default. |
while removing dir or file, it happens that EBUSY error could happen with file being used and lock. This is a simple way to wait for file to be unlocked, with a fail safe of max try to avoid infinite loop.
On windows, while working in VS CODE with Quarto Dev version, I often encounter this error
Example of stacktrace when this happens
Debugging this, I found this is due to
EBUSY
code from DenoremoveSync()
, and means somehow file is locked on windows and prevents Deno to remove it.This is quite annoying so I wanted to find a solution. My guess is that this is race constraint, and file will be unlock quickly but not quickly enough for Deno to remove it safely.
Here is a suggestion to add a retry until this works. max try is high because each retry is very quick and it happens I encounter the issue even with 100 retry.
What do you think of something like this ?
Other way would be to use
await Deno.remove()
and see if this has the same issue asDeno.removeSync()
. If not, we could use it, but we need to replace everywhere with non-Sync version which is bigger change and impact