aspnetcore: Blazor - BrotliCompress msbuild task duplicate processing of files - causes lock exceptions
Describe the bug
There appears to be an issue with the BrotliCompress task (and I am assuming might not be limited to the BrotliCompress task - if there are others that resolve content to process in a similar way) whereby, a single file in the project appears to be processed twice if you have a particular project entry.
This issue (duplicate entries to process) can then go on to cause an exception, because the BrotliCompress task later processes those entries (files) in parrallel - and if one parallel task doesn’t release the lock on the file before the other parallel tasks processes the duplicate entry / file, you get the msbuild failure during the dotnet publish as originally described here where more than one parallel task is trying to lock the same file.
To Reproduce
- Create a vanilla blazor hosted wasm project.
- Add the following entry the client (wasm) csproj file:
<ItemGroup>
<_ContentIncludedByDefault Remove="wwwroot\css\app.css" />
</ItemGroup>
Do a dotnet publish -c Release -v Detailed and inspect the output, note that the app.css file appears to be processed twice by the brotli task:
Done executing task "MakeDir".
Using "BrotliCompress" task from assembly "C:\hostedtoolcache\windows\dotnet\sdk\5.0.102\Sdks\Microsoft.NET.Sdk.BlazorWebAssembly\targets\..\tasks\net5.0\Microsoft.NET.Sdk.BlazorWebAssembly.Tasks.dll".
Task "BrotliCompress"
C:\hostedtoolcache\windows\dotnet\dotnet.exe "C:\hostedtoolcache\windows\dotnet\sdk\5.0.102\Sdks\Microsoft.NET.Sdk.BlazorWebAssembly\targets\..\tools\net5.0\Microsoft.NET.Sdk.BlazorWebAssembly.Tools.dll" brotli
-s
D:\a\1\s\src\Foo.Client\wwwroot\appsettings.Development.json
-o
D:\a\1\s\src\Foo.Client\obj\Release\net5.0\compress\kMn0BpPF.br
-s
D:\a\1\s\src\Foo.Client\wwwroot\appsettings.json
-o
D:\a\1\s\src\Foo.Client\obj\Release\net5.0\compress\mnsMCpbd.br
-s
D:\a\1\s\src\Foo.Client\wwwroot\css\app.css
-o
D:\a\1\s\src\Foo.Client\obj\Release\net5.0\compress\ht+9vXXP.br
-s
D:\a\1\s\src\Foo.Client\wwwroot\css\app.css
-o
D:\a\1\s\src\Foo.Client\obj\Release\net5.0\compress\ht+9vXXP.br
-s
D:\a\1\s\src\Foo.Client\wwwroot\css\app.min.css
And the dotnet publish failure that happens if locks aren’t released in time:
The process cannot access the file ‘D:\a\1\s\src\Foo.Client\obj\Release\net5.0\compress\ht+9vXXP.br’ 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) at Microsoft.NET.Sdk.BlazorWebAssembly.Tools.BrotliCompressCommand.<ExecuteCoreAsync>b__16_0(Int32 i) at System.Threading.Tasks.Parallel.<>c__DisplayClass19_0
1.<ForWorker>b__1(RangeWorker& currentWorker, Int32 timeout, Boolean& replicationDelegateYieldedBeforeCompletion) --- End of stack trace from previous location --- at System.Threading.Tasks.Parallel.<>c__DisplayClass19_01.<ForWorker>b__1(RangeWorker& currentWorker, Int32 timeout, Boolean& replicationDelegateYieldedBeforeCompletion) at System.Threading.Tasks.TaskReplicator.Replica`1.ExecuteAction(Boolean& yieldedBeforeCompletion) at System.Threading.Tasks.TaskReplicator.Replica.Execute()
4:5>C:\hostedtoolcache\windows\dotnet\sdk\5.0.102\Sdks\Microsoft.NET.Sdk.BlazorWebAssembly\targets\Microsoft.NET.Sdk.BlazorWebAssembly.Current.targets(564,5): error MSB6006: “C:\hostedtoolcache\windows\dotnet” exited with code 1. [D:\a\1\s\src\Foo.Client\Foo.Client.csproj] Done executing task “BrotliCompress” – FAILED.
Removing this project entry fixes the problem.
Note: I am not sure why my project had this entry, but it has been upgraded over a long period of time, removing the entry seems to be a valid workaround in my case however I raise the issue as it seems like this shouldn’t be causing the issue that it does…
Exceptions (if any)
as per above
Further technical details
- ASP.NET Core version: 5.0.2
- Include the output of
dotnet --info - The IDE (VS / VS Code/ VS4Mac) you’re running on, and its version
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 4
- Comments: 15 (8 by maintainers)
@ejhg - yeah its not exclusive to any particular file. Its a combination of the compression task picking up duplicate msbuild entries (i.e trying to process the same project item twice) and the fact it processes / compresses those items in parallel on disk. In my case the file in question had a particular project entry as described above, removing that caused the duplicate processing to go away. If you run dotnet publish with verbosity detailed (and Release configuration) you should be able to search the output log for that file hash and see whether its being picked up as two msbuild items. Then check your csproj to see how that file is included into the project.
A quick fix for the compression task could be to make sure it has a set of distinct files, before it does its parallel processing. Another fix could be to make sure the msbuild items that are picked up in the first place relate to a distinct set of files but perhaps that is harder.