Skip to content

Commit

Permalink
Prevent concurrent restore of same project.json
Browse files Browse the repository at this point in the history
DNX has an issue with concurrent restore: aspnet/dnx#1682

Previously I would workaround by copying to intermediate, but this breaks in official build where intermediate is not under the scope of our nuget.config, so custom package sources are ignored.

Fix this instead by wrapping the call to dnu restore with a mutex unique to the project.json name.  We only need to do this for the test project.json because that is the only one we'll restore concurrently.
  • Loading branch information
ericstj committed Apr 21, 2015
1 parent d7ee4f8 commit 4ada52d
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 9 deletions.
44 changes: 44 additions & 0 deletions src/Microsoft.DotNet.Build.Tasks/ExecWithMutex.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Microsoft.Build.Framework;
using Microsoft.Build.Tasks;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.DotNet.Build.Tasks
{
public class ExecWithMutex : Exec
{
[Required]
public string MutexName
{
get;
set;
}

protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)
{
string actualMutexName = MutexName.Replace(Path.DirectorySeparatorChar, '_');
bool created = false;

using (Mutex mutex = new Mutex(true, actualMutexName, out created))
{
try
{
if (!created)
{
mutex.WaitOne();
}
return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands);
}
finally
{
mutex.ReleaseMutex();
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
</PropertyGroup>
<ItemGroup>
<Compile Include="ExecWithMutex.cs" />
<Compile Include="GenerateResourcesCode.cs" />
<Compile Include="GetWorkspaceBranch.cs" />
<Compile Include="GitTag.cs" />
Expand All @@ -41,6 +42,7 @@
<Compile Include="ResolveNuGetPackages.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Build.Tasks.v4.0" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="mscorlib" />
<Reference Include="LibGit2Sharp">
Expand Down
12 changes: 3 additions & 9 deletions src/Microsoft.DotNet.Build.Tasks/Targets/publishtest.targets
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<UsingTask TaskName="ExecWithMutex" AssemblyFile="$(ToolsDir)Microsoft.DotNet.Build.Tasks.dll"/>
<UsingTask TaskName="ResolveNuGetPackages" AssemblyFile="$(ToolsDir)Microsoft.DotNet.Build.Tasks.dll"/>
<UsingTask TaskName="ResolveNuGetPackageAssets" AssemblyFile="$(ToolsDir)Microsoft.DotNet.Build.Tasks.dll"/>

Expand All @@ -20,18 +21,11 @@

<Exec Command="$(NugetRestoreCommand) &quot;$(TestRuntimePackageConfig)&quot;" StandardOutputImportance="Low" />

<!-- DNU will emit a project.lock.json. When multiple tests are building for the first time they may race on
running this target and generating the lock.json. This is causing IOExceptions in dnu for writing lock.json.
We should really be handling these test dependencies in a different way (as a package themselves) but for now
just restore the project.json from intermediate to avoid the race. -->
<Copy SourceFiles="$(TestRuntimeProjectJson)" DestinationFolder="$(IntermediateOutputPath)">
<Output TaskParameter="CopiedFiles" PropertyName="TempTestRuntimeProjectJson"/>
</Copy>
<Exec Command="$(DnuRestoreCommand) &quot;$(TempTestRuntimeProjectJson)&quot;" StandardOutputImportance="Low" CustomErrorRegularExpression="^Unable to locate .*" />
<ExecWithMutex Command="$(DnuRestoreCommand) &quot;$(TestRuntimeProjectJson)&quot;" MutexName="$(TestRuntimeProjectJson)" StandardOutputImportance="Low" CustomErrorRegularExpression="^Unable to locate .*" />

<!-- Always copy since we need to force a timestamp update for inputs/outputs-->
<Copy SourceFiles="$(TestRuntimePackageConfig)" DestinationFiles="$(TestRuntimePackageSemaphore)" ContinueOnError="true" SkipUnchangedFiles="false" />
<Copy SourceFiles="$(IntermediateOutputPath)/project.lock.json" DestinationFiles="$(TestRuntimeProjectLockJson)" ContinueOnError="true" SkipUnchangedFiles="false" />
<Copy SourceFiles="$(MSBuildThisFileDirectory)test-runtime\project.lock.json" DestinationFiles="$(TestRuntimeProjectLockJson)" ContinueOnError="true" SkipUnchangedFiles="false" />
</Target>

<Target Name="GetTestNugetPackageReferences"
Expand Down

0 comments on commit 4ada52d

Please sign in to comment.