Statiq.Framework: Certain editors throw file access error on live preview
When editing files in VSCode or Notepad++ with the live preview running, I see the following error on each save:
[ERRO] Inputs/Process » ExecuteIf » ExtractFrontMatter » [D:/dev/teststatiq/TestSite/input/test.md => test.md] The process cannot access the file ‘D:\dev\teststatiq\TestSite\input\test.md’ because it is being used by another process.
This is consistent on every save from vscode or notepad++, but saving a file in notepad causes the rebuild to happen without issue.
I’ve replicated this on a fresh project, using just these steps:
dotnet new console --name TestSite
cd TestSite
dotnet add package Statiq.Web --version 1.0.0-beta.13
code .
Updated Program.cs as per the docs, and added input/test.md
dotnet run
Verified that the file in output is generated fine.
dotnet run -- preview
Edit page in vscode and save, I see the error. Immediately edit using notepad, no error.
Other info: VSCode: 1.51.1 Windows 10: 19041 Dotnet: 5.0.100
The full error with -l Debug enabled:
[ERRO] Inputs/Process » ExecuteIf » ExtractFrontMatter » [D:/dev/teststatiq/TestSite/input/test.md => test.md] The process cannot access the file 'D:\dev\teststatiq\TestSite\input\test.md' because it is being used by another process. [DBUG] Exception while executing pipeline Inputs/Process: System.IO.IOException: The process cannot access the file 'D:\dev\teststatiq\TestSite\input\test.md' because it is being used by another process. at System.IO.FileStream.ValidateFileHandle(SafeFileHandle fileHandle) at System.IO.FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean useAsync) at Statiq.Core.LocalFile.OpenRead() at Statiq.Common.FileContent.GetStream() at Statiq.Common.IDocumentExtensions.GetContentStream(IDocument document) at Statiq.Common.IDocumentExtensions.GetContentStringAsync(IDocument document) at Statiq.Core.ExtractFrontMatter.ExecuteInputAsync(IDocument input, IExecutionContext context) at Statiq.Common.Module.ExecuteInputFuncAsync(IDocument input, IExecutionContext context, Func`3 executeFunc)
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 17 (10 by maintainers)
Commits related to this issue
- Added more retry logic to the local file abstraction (#151) — committed to statiqdev/Statiq.Framework by daveaglick 4 years ago
Yay! Guess we can put this one to rest for now. If it pops back up, please reopen this issue and I’ll continue working the problem.
And yeah, Polly is a great little library. One of those ones I tend to add to every project because it does one thing really well that we usually have to do all the time anyway.
Initial testing looks good to me! The extra delay before the processing kicks in is I think noticeable (as in, it doesn’t fail instantly like before, so very much looks like it’s working as designed), but only because I’m watching for it - it’s still plenty fast enough for the purpose. And thanks for the introduction to Polly… I think I can find some uses for that myself…!
Caught red-handed!
I’m on to something, almost positive this is related somehow to the .NET runtime. I tried unsuccessfully over probably 100 executions to trigger the lock error with no joy. Then I (finally) installed the .NET 5 SDK onto my main development box, confirmed the
dotnetmuxer had switched to the .NET 5 runtime, and was able to reproduce within 2 or 3 executions.Just as another data point - I just noticed that beta 14 was out a week or so ago (vs the 13 I was using) and updated to it. It seems that in that version it “works” in that it fails as before, but then attempts to do the whole thing again immediately? It means the live reload in the browser still breaks (on the first attempt), but manually refreshing then loads up the site. Or at least there’s a change in behaviour where after failing the first time, it sees the file has been changed again (that’s what the logs say) and reruns.
I’ll give the next release a go when it’s out/I have a few minutes!
I still haven’t been able to reproduce this locally, but I have observed it on other systems now. The behavior is exactly as you describe. At one point VS Code even complained of a locked file it was saving (which may be a clue that there’s some interesting back-and-forth going on with multiple file system events).
The next release due out today includes a rewrite of the file system watcher to include some event debouncing. I needed it anyway, but it might help with this problem as well 🤞.
Thanks a lot for following up, these are great data points. I’m going to try playing around with VMs and different .NET SDKs to see if I can reproduce the problem - the SDK version might be a total red herring, but seems like a good place to start.