coverlet icon indicating copy to clipboard operation
coverlet copied to clipboard

Could not write lines to file CoverletSourceRootsMapping - in use by another process

Open ta264 opened this issue 3 years ago • 30 comments

Our build process with coverlet > 3.0 tends to fail with an error like this:

C:\Users\VssAdministrator\.nuget\packages\coverlet.collector\3.0.4-preview.25\build\netstandard1.0\coverlet.collector.targets(48,5): error MSB3491: Could not write lines to file "..\..\_tests\net5.0\linux-musl-arm64\CoverletSourceRootsMapping". The process cannot access the file 'D:\a\1\s\_tests\net5.0\linux-musl-arm64\CoverletSourceRootsMapping' because it is being used by another process. [D:\a\1\s\src\NzbDrone.Host.Test\Radarr.Host.Test.csproj]
  Radarr.Windows.Test -> D:\a\1\s\_tests\net5.0\linux-musl-x64\publish\

I suspect this is because we have a centralized output directory (not one per project).

  <PropertyGroup>
    <!-- Output to _output and _tests respectively -->
    <OutputPath Condition="'$(RadarrProject)'=='true'">$(RadarrRootDir)_output\</OutputPath>
    <OutputPath Condition="'$(RadarrOutputType)'=='Test'">$(RadarrRootDir)_tests\</OutputPath>
  </PropertyGroup>

Can this be worked around at all?

ta264 avatar Apr 27 '21 10:04 ta264

Unfortunately at the moment CoverletSourceRootsMapping uses $OutputPath https://github.com/coverlet-coverage/coverlet/blob/master/src/coverlet.collector/build/netstandard1.0/coverlet.collector.targets#L46

MarcoRossignoli avatar May 04 '21 20:05 MarcoRossignoli

I have the same issue. Looks like as a workaround we can build tests into a subdirectory of that centralized directory.

LevYas avatar May 07 '21 17:05 LevYas

@LevYas can you expand on your workaround? I'm using --output flag with the dotnet cli so I don't specify the output at the project level but the solution I'm building contains multiple projects. Does that mean a different build output needs to be specified in each project file in the solution and I can't use the cli --output flag? Seems like an arduous workaround that's error prone if you expect to put this all into an automated build.

If this is a race condition (I expect it is as I run into about 75% of the time), can it be solved with some retry logic? I grabbed the following from the same dotnet publish step and there is some retry logic going on so I'm wondering if the same can be done for the CoverletSourceRootsMapping file:

Copying file from "C:\Users\ContainerAdministrator\.nuget\packages\coverlet.collector\3.0.3\build\netstandard1.0\System.Linq.Expressions.dll" to "C:\__w\165\b\SampleAPI\System.Linq.Expressions.dll".
9:6>C:\Users\ContainerAdministrator\.nuget\packages\coverlet.collector\3.0.3\build\netstandard1.0\coverlet.collector.targets(16,5): warning MSB3026: Could not copy "C:\Users\ContainerAdministrator\.nuget\packages\coverlet.collector\3.0.3\build\netstandard1.0\System.Linq.Expressions.dll" to "C:\__w\165\b\SampleAPI\System.Linq.Expressions.dll". Beginning retry 1 in 1000ms. The process cannot access the file 'C:\__w\165\b\SampleAPI\System.Linq.Expressions.dll' because it is being used by another process.  [C:\__w\165\s\project\API\Sample.Tests\Sample.Tests.csproj]

MrOwen avatar May 13 '21 00:05 MrOwen

@MrOwen Sure. I have output setup per project for all my projects, and I use CI/CD. Here's how it looks like for test project:

<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath
<OutputPath>..\..\..\Bin\$(Configuration)\Tests\Unit</OutputPath>

LevYas avatar May 13 '21 07:05 LevYas

Ah, that's what I was afraid of. I'm working on a project with 60 test projects... I actually ended up upgrading Microsoft.NET.Test.Sdk, MSTest.TestAdapter, and MSTest.TestFramework to their latest versions since we were way behind and all issues seem to have gone away. Tried looking in the changelogs for each of these to see if some sort of race-condition was fixed but didn't spot any specifically. Either way, for future peeps stumbling on this problem, there's a few fixes in this thread now. Thanks again @LevYas!

MrOwen avatar May 13 '21 22:05 MrOwen

We had the same problem now. Our "workaround" for now was to only build with a single process instead of multiple. Not ideal though as the build will take longer once the solution grows.

echalone avatar Oct 20 '21 14:10 echalone

Same problem here. Build with single process with a solution >50 projects is not an option.

zplan avatar Nov 12 '21 09:11 zplan

For now a possible solutions could be update coverlet to write the mapping in a folder like $(OutputPath)\CoverletSourceMappings\CoverletSourceRootsMapping_{Guid}` and merge/use when needed.

MarcoRossignoli avatar Nov 12 '21 11:11 MarcoRossignoli

Hello!

Any development on this subject? It seems since we migrated to .net6, the bug occurs almost always. We did not have the problem before that.

cboulva99 avatar Jan 03 '22 13:01 cboulva99

Hello!

Any development on this subject? It seems since we migrated to .net6, the bug occurs almost always. We did not have the problem before that.

Yes, we observe the same - 85% chance of error, prior to net6 we haven't seen this error.

maxpavlov avatar Jan 09 '22 14:01 maxpavlov

Any word on the progress, or if the community should aim to assist on this fix? For efficiency purposes, we keep our tests in an Output\Tests\ folder in our projects for accessibility, reduction of multiple DLLs, and easy-to-clean purposes.

However, we continuously get the error, "The process cannot access the file '...\CoverletSourceRootsMapping' because it is being used by another process. This is problematic for our build machines.

Thank you.

DamianSuess avatar Feb 01 '22 19:02 DamianSuess

It's on high priority, but didn't have time to work on it yet, bit busy times.

Can someone provide a repro to speedups a bit the analysis?

Coverlet is open source if someone wants to take this one I'm glad to review and help. In case let me know that I'll assign the issue to avoid to accidentally waste time.

MarcoRossignoli avatar Feb 01 '22 19:02 MarcoRossignoli

We have the same issue, basically the scenario is:

  • a solution with multiple test projects
  • output to the same folder
  • build the solution (with msbuild /m to enable msbuild concurrency)

Since this is a "build timing" bug related to writing to the same file, it is not 100% reproducable.

However, I think a good fix would probably be to append or prefix the MSBuildProjectName to the CoverletSourceRootsMapping file, e.g.

_sourceRootMappingFilePath: "$([MSBuild]::EnsureTrailingSlash('$(OutputPath)'))CoverletSourceRootsMapping -$(MSBuildProjectName)"

This will ensure that the CoverletSourceRootsMapping file is unique per MSBuildProject (i.e. per Assembly)

japj avatar Feb 23 '22 07:02 japj

I'm all for @japj's suggestion, it's cleaner than a GUID suffix. If we created a branch for this, are there sufficient existing unit tests against this to support such a change?

DamianSuess avatar Feb 23 '22 13:02 DamianSuess

I don't think that is enough only update with the guid some code needs review

https://github.com/coverlet-coverage/coverlet/blob/master/src/coverlet.core/Helpers/SourceRootTranslator.cs https://github.com/coverlet-coverage/coverlet/blob/master/src/coverlet.core/Reporters/CoberturaReporter.cs#L71

Tests are here https://github.com/coverlet-coverage/coverlet/blob/master/test/coverlet.integration.tests/DeterministicBuild.cs

MarcoRossignoli avatar Feb 23 '22 14:02 MarcoRossignoli

Thank you, Marco, for providing your insight & experience to help keep this moving 👍

DamianSuess avatar Feb 25 '22 00:02 DamianSuess

I've started to work on this one the idea is to create the file mapping using some sort of hash for the "current" test container to avoid collision in case of solutions with more containers in the same output folder. Something like image Let's see it it can work...there're some place to change:

  • targets msbuild/collectors
  • SourceRootTranslator
  • Tests

cc: @daveMueller

MarcoRossignoli avatar Mar 19 '22 18:03 MarcoRossignoli

Hi all,

I've published a test package here https://f.feedz.io/marcorossignoli/coverletunofficial/nuget/index.json the versions are

coverlet.collector 3.1.3-preview.7.gb1603b798b coverlet.msbuild 3.1.3-preview.7.gb1603b798b

I need help, can someone give it a try and let me know if it's working?

MarcoRossignoli avatar Mar 20 '22 16:03 MarcoRossignoli

@MarcoRossignoli: I can confirm that coverlet.collector 3.1.3-preview.7.gb1603b798b fixed the problem on my end.

bretthysuik avatar Mar 21 '22 16:03 bretthysuik

thanks @bretthysuik can you confirm that in you output folder you see a list of CoverletSourceRootsMapping_dlltestname?

Can someone else give a try to coverlet.msbuild 3.1.3-preview.7.gb1603b798b?

MarcoRossignoli avatar Mar 21 '22 18:03 MarcoRossignoli

Yes, a CoverletSourceRootsMapping_dlltestname.Tests file was created for every test project in the solution.

bretthysuik avatar Mar 21 '22 18:03 bretthysuik

Works for me as well.

walljumper avatar Mar 28 '22 10:03 walljumper

Can someone cover the coverlet.msbuild use case pls?

MarcoRossignoli avatar Mar 28 '22 12:03 MarcoRossignoli

Can someone cover the coverlet.msbuild use case pls?

coverlet.msbuild 3.1.3-preview.7.gb1603b798b looks to be working as well. A coverage.json file is created for each test project in the solution, and no errors occurred related to CoverletSourceRootsMapping.

bretthysuik avatar Apr 05 '22 16:04 bretthysuik

Thanks for the testing.

MarcoRossignoli avatar Apr 08 '22 07:04 MarcoRossignoli

Is there a target release date for the 3.1.3 version?

LucidoKeith avatar May 24 '22 12:05 LucidoKeith

Not yet, I'm having issue with this fix in CI...I need to investigate a bit more.

MarcoRossignoli avatar May 24 '22 12:05 MarcoRossignoli

Any update on the official 3.1.3 version?

C302 avatar Aug 02 '22 09:08 C302

This fix is not yet merged...I'm having some hassle on tests and I'm a bit busy, I'll try to work on it asap.

MarcoRossignoli avatar Aug 06 '22 09:08 MarcoRossignoli

Any update on the 3.1.3 version?

ravi-chandra-gl avatar Sep 08 '22 13:09 ravi-chandra-gl