Skip to content

Fix compiler server on CoreCLR and enable bootstrapping on CoreCLR build#24239

Merged
agocke merged 15 commits intodotnet:dev15.6.xfrom
agocke:bootstrap-coreclr-server
Jan 23, 2018
Merged

Fix compiler server on CoreCLR and enable bootstrapping on CoreCLR build#24239
agocke merged 15 commits intodotnet:dev15.6.xfrom
agocke:bootstrap-coreclr-server

Conversation

@agocke
Copy link
Copy Markdown
Member

@agocke agocke commented Jan 15, 2018

Customer scenario

This PR fixes the CoreCLR compiler server on Windows and changes our bootstrap build to act as a test case. The bug in the compiler server was we were attempting to do user ID verification on CoreCLR on Windows, but those APIs are not available on CoreCLR, so this would always fail. This fix disables user ID verification and relies only on Windows pipe ACLs, which should be enough to ensure that only properly privileged users can connect.

Bugs this fixes

Fixes #20900 and #24072

Workarounds, if any

There are no workarounds for using the compiler server under CoreCLR on Windows.

Risk

This change is substantially similar to what we do on Linux, so has already been given a fair amount of coverage.

Performance impact

This should make the compiler much faster on CoreCLR.

Is this a regression from a previous update?

No.

Root cause analysis

We didn't bootstrap using the compiler server on CoreCLR, which I've now added.

How was the bug found?

Customer reported.

@agocke agocke added this to the 15.6 milestone Jan 15, 2018
@agocke agocke requested review from a team and jaredpar January 15, 2018 07:47
@agocke agocke requested a review from a team as a code owner January 15, 2018 07:47
netci.groovy Outdated
description("Windows CoreCLR unit tests")
steps {
batchFile(""".\\build\\scripts\\cibuild.cmd ${(configuration == 'debug') ? '-debug' : '-release'} -testCoreClr""")
batchFile("""powershell -noprofile -executionPolicy RemoteSigned -file .\\build\\scripts\\cibuild.cmd ${(configuration == 'debug') ? '-debug' : '-release'} -restore -cibuild -bootstrap -coreClrBuild -testCoreClr -binaryLog""")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks wrong. It's using powershell to target a CMD file. Not sure why we'd change this to use powershell here in any case.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this should have been build.ps1. The problem is that cibuild.cmd passes the -build arg, which I made incompatible with -coreClrBuild. Would you prefer that both flags are required, and coreClrBuild just forces coreclr instead of desktop?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would do the following:

  • Rename -coreClrBuild to -buildCoreClr.
  • Allow mixing of -build and -buildCoreClr. Would actually set -build to true if -buildCoreClr is true in Process-Arguments

This would give -buildCoreClr a lot of symetry with -buildAll

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I didn't do that is because, unlike buildAll, this doesn't build the same stuff as -build (it only builds Compilers.sln). Is that still OK?


<PropertyGroup>
<!-- Don't use the compiler server by default in the NuGet package. -->
<UseSharedCompilation Condition="'$(UseSharedCompilation)' == ''">false</UseSharedCompilation>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we making this change? We made this "true" by default in the NuGet package in response to customer feedback here around performance.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that's true -- this matches the desktop behavior as far as I can see.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any projects using the "new" project format will have UseSharedCompilation set to true by default: https://github.com/dotnet/sdk/blob/8a24663345cc5952062cb898431dbd8800b4da85/src/Tasks/Microsoft.NET.Build.Tasks/build/Microsoft.NET.Sdk.targets#L428

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<UseSharedCompilation Condition="'$(UseSharedCompilation)' == ''">false</UseSharedCompilation>

I'm not sure why the line above says "in Visual Studio" -- this applies to the NuGet package.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tannergooding That line won't be evaluated until after we evaluate this property if the package is installed via NuGet.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but this line will prevent the compiler server from being used on new SDK which has a different default from Desktop.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tannergooding The same property is set on Desktop:

<PropertyGroup Condition="'$(UseSharedCompilation)' == ''">

}

if ($build -and $coreClrBuild)
{
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Powershell braces start on same line as previous construct.

Move-Item "$configDir\Exes\Toolset\*" $dir
if ($coreClrBuild) {
$bootstrapFramework = "netcoreapp2.0"
Exec-Console "dotnet" "publish --no-restore src/Compilers/CSharp/csc -o `"$dir/bincore`" --framework $bootstrapFramework $bootstrapArgs -bl:$binariesDir/BootstrapCsc.binlog"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Log files should go into Binaries\Logs

}
}


Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extraneous blank line.

@agocke agocke requested a review from a team January 16, 2018 23:46
@agocke
Copy link
Copy Markdown
Member Author

agocke commented Jan 17, 2018

@jaredpar Can you take another look at this? I think I've addressed your comments.

{
// CoreCLR doesn't have these APIs, so we just have to rely on
// Windows ACLs for security
return true;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately at this point on CoreClr we don't have ACLs

https://github.com/dotnet/corefx/issues/24040

This means we no longer have ACLs or identity verification.

Exec-Console "dotnet" "publish --no-restore src/Compilers/VisualBasic/vbc -o `"$dir/bincore`" --framework $bootstrapFramework $bootstrapArgs -bl:$logDir/BootstrapVbc.binlog"
Exec-Console "dotnet" "publish --no-restore src/Compilers/Server/VBCSCompiler -o `"$dir/bincore`" --framework $bootstrapFramework $bootstrapArgs -bl:$logDir/BootstrapVBCSCompiler.binlog"
Exec-Console "dotnet" "publish --no-restore src/Compilers/Core/MSBuildTask -o `"$dir`" $bootstrapArgs -bl:$binariesDir/BootstrapMSBuildTask.binlog"
Exec-Console "dotnet" "$dir/bincore/VBCSCompiler.dll" -shutdown
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add exec to be explicit here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exec is not really supported, AFAIK. The official guidance is just to pass the DLL as an argument.

function Build-Artifacts() {
if ($build) {
if ($buildCoreClr)
{
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open braces same line.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open braces on same line.

}

if ($build -or $pack) {
if ($build -or $buildCoreClr -or $pack) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should be consistent with $buildAll here. Inside Process-Arguments we should set $build to $true if $buildCoreClr is also $true.

$args += " $projectFilePath"
Exec-Console $msbuild $args

if ($useDotnetBuild)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Braces same line in powershell

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping

Exec-Console "dotnet" "publish --no-restore src/Compilers/CSharp/csc -o `"$dir/bincore`" --framework $bootstrapFramework $bootstrapArgs -bl:$logDir/BootstrapCsc.binlog"
Exec-Console "dotnet" "publish --no-restore src/Compilers/VisualBasic/vbc -o `"$dir/bincore`" --framework $bootstrapFramework $bootstrapArgs -bl:$logDir/BootstrapVbc.binlog"
Exec-Console "dotnet" "publish --no-restore src/Compilers/Server/VBCSCompiler -o `"$dir/bincore`" --framework $bootstrapFramework $bootstrapArgs -bl:$logDir/BootstrapVBCSCompiler.binlog"
Exec-Console "dotnet" "publish --no-restore src/Compilers/Core/MSBuildTask -o `"$dir`" $bootstrapArgs -bl:$binariesDir/BootstrapMSBuildTask.binlog"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why aren't we killing the server here

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No server to kill. The server can't be used via NuGet package until this is merged :)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But once this is merged will need to kill the server. I would add back the kill and just catch the failure condition.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping on this Q

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added Stop-BuildProcesses at the end here, so when this works we'll be all set.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@agocke Don't you want to do it at the beginning in case there is detritus from a previous run? Imagine somebody running this script locally to test changes.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that's the purpose of the call in the try-finally at the top-level.

Certain dependent assemblies (System.IO.Pipes,
System.IO.Pipes.AccessControl) are operating system dependent and thus
end up in the runtimes subdirectory next to the build task.
Unfortunately, there is no mechanism for automatic assembly resolution
of plugin DLLs like MSBuild tasks, so we have to implement something
similar ourselves. This change hooks assembly resolution and, when we
see a well-known DLL request, we redirect it to the appropriate path.
@agocke agocke force-pushed the bootstrap-coreclr-server branch from 38b64e6 to 34ed6fc Compare January 23, 2018 05:10
<UseSharedCompilation>false</UseSharedCompilation>
<!-- Older versions of the CLI didn't set the DOTNET_HOST_PATH variable, which
means we have to use our shell wrappers and hope 'dotnet' is on the path. -->
<PropertyGroup Condition="'$(DOTNET_HOST_PATH)' == ''">
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we file an issue to track deleting this? Once we get past 2.1 we should no longer support this case.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we'll have to support installing newer compilers on older runtimes for quite a while, no? Is there any reason not to support that, if this is the only complexity?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't think it was possible at all in older CLI. Could be wrong.

Condition="'$(BuildingProject)' == 'true' AND '$(OS)' != 'Windows_NT'"
Condition="'$(BuildingProject)' == 'true' AND
'$(OS)' != 'Windows_NT' AND
'$(CscToolPath)' != ''"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't agree with the CscToolPath condition here. Consider the case where only CscToolPath was set but not VbcToolPath. In that case we still need to make the scripts executable.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah good point.

[switch]$pack = $false,
[switch]$binaryLog = $false,
[string]$signType = "",
[switch]$buildCoreClr = $false,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please group this with the other build options.

$args += " $projectFilePath"
Exec-Console $msbuild $args

if ($useDotnetBuild)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping

Exec-Console $dotnet $args
}
else
{
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open Braces on same line in powershell.

}

private static readonly string s_assemblyLocation = Utilities.TryGetAssemblyPath(typeof(AssemblyResolution).GetTypeInfo().Assembly);
private static Assembly TryRedirectToRuntimesDir(AssemblyName name)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a bug tracking the undo'ing of this at a later date?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will we actually undo it? I'm not sure MSBuild or CoreCLR are going to do anything about this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The solution can't be this code though. We need to file a bug with CoreClr to get them to tell us the right way to do this, or provide an assembly load context that has rationale behavior.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also filed #24397

<file src="Dlls/MSbuildTask/netstandard1.3/publish/Microsoft.VisualBasic.Core.targets" target="tools" />
<!-- N.B.: The backslashes below cannot be replaced with forward slashes. -->
<file src="Dlls\MSBuildTask\netstandard1.3\publish\System.*.dll" target="tools" />
<file src="Dlls\MSBuildTask\netstandard1.3\publish\runtimes\**" target="tools\runtimes" />
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we pick \ or / for the slash direction? Don't care which we use, just prefer we use one of them.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm now worried about changing anything here because I have no idea what it will do to the package layout.

<file src="Exes/VBCSCompiler/netcoreapp2.0/publish/VBCSCompiler.runtimeconfig.json" target="tools/bincore" />

<!-- References that are either not in the target framework or are a higher version -->
<!-- N.B.: The backslashes below cannot be replaced with forward slashes. -->
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to ask but I have to ... why?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like NuGet has different behavior -- the backslashes are interpreted as "everything in this directory" while forward slashes are "the entire directory tree, including parent directories"

function Build-Artifacts() {
if ($build) {
if ($buildCoreClr)
{
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open braces on same line.

case "System.Reflection":
return TryRedirect(name, s_b03f5f7f11d50a3a, 4, 1, 1, 0);

// Assemblies in the runtimes directory
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please expand the comment on why this makes a difference.

}

private static readonly string s_assemblyLocation = Utilities.TryGetAssemblyPath(typeof(AssemblyResolution).GetTypeInfo().Assembly);
private static Assembly TryRedirectToRuntimesDir(AssemblyName name)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The solution can't be this code though. We need to file a bug with CoreClr to get them to tell us the right way to do this, or provide an assembly load context that has rationale behavior.

@agocke agocke dismissed jaredpar’s stale review January 23, 2018 19:17

Jared signed off in-person

Copy link
Copy Markdown
Member

@VSadov VSadov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@agocke agocke merged commit c1b6173 into dotnet:dev15.6.x Jan 23, 2018
@agocke agocke deleted the bootstrap-coreclr-server branch January 23, 2018 20:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants