Skip to content
This repository has been archived by the owner on Apr 20, 2023. It is now read-only.

Commit

Permalink
Fix Razor server shutdown on Windows.
Browse files Browse the repository at this point in the history
On Windows, the Razor server correctly creates the pid file with
`FileAccess.Write` and `FileOptions.DeleteOnClose`.  This requires a share mode
of `FileShare.Write | FileShare.Delete` to open.  However, the
`dotnet build-server shutdown` command was opening the file with
`FileShare.Read`.  As a result, an `IOException` was being thrown and was not
handled.

This change first opens the file with the appropriate share access and also
properly handles a failure to access or read the contents of the pid file.

Additionally, an integration test was added to test that Razor server shutdown
works as expected.

Fixes #9158.
  • Loading branch information
Peter Huene committed Apr 27, 2018
1 parent 04066cb commit b2b3947
Show file tree
Hide file tree
Showing 23 changed files with 260 additions and 6 deletions.
@@ -0,0 +1,16 @@
@page
@model TestRazorApp.MyFeature.Pages.Page1Model
@{
Layout = null;
}

<!DOCTYPE html>

<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Page1</title>
</head>
<body>
</body>
</html>
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace TestRazorApp.MyFeature.Pages
{
public class Page1Model : PageModel
{
public void OnGet()
{

}
}
}
11 changes: 11 additions & 0 deletions TestAssets/TestProjects/TestRazorApp/TestRazorApp.csproj
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), testAsset.props))\testAsset.props" />

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="$(MicrosoftAspNetCoreAllPackageVersion)" />
</ItemGroup>
</Project>
27 changes: 24 additions & 3 deletions src/dotnet/BuildServer/BuildServerProvider.cs
Expand Up @@ -12,15 +12,19 @@ namespace Microsoft.DotNet.BuildServer
{
internal class BuildServerProvider : IBuildServerProvider
{
public const string PidFileDirectoryVariableName = "DOTNET_BUILD_PIDFILE_DIRECTORY";
private readonly IFileSystem _fileSystem;
private readonly IEnvironmentProvider _environmentProvider;
private readonly IReporter _reporter;

public BuildServerProvider(
IFileSystem fileSystem = null,
IEnvironmentProvider environmentProvider = null)
IEnvironmentProvider environmentProvider = null,
IReporter reporter = null)
{
_fileSystem = fileSystem ?? FileSystemWrapper.Default;
_environmentProvider = environmentProvider ?? new EnvironmentProvider();
_reporter = reporter ?? Reporter.Error;
}

public IEnumerable<IBuildServer> EnumerateBuildServers(ServerEnumerationFlags flags = ServerEnumerationFlags.All)
Expand Down Expand Up @@ -59,7 +63,7 @@ public IEnumerable<IBuildServer> EnumerateBuildServers(ServerEnumerationFlags fl
if ((flags & ServerEnumerationFlags.Razor) == ServerEnumerationFlags.Razor &&
Path.GetFileName(path).StartsWith(RazorPidFile.FilePrefix))
{
var file = RazorPidFile.Read(new FilePath(path), _fileSystem);
var file = ReadRazorPidFile(new FilePath(path));
if (file != null)
{
yield return new RazorServer(file);
Expand All @@ -70,7 +74,7 @@ public IEnumerable<IBuildServer> EnumerateBuildServers(ServerEnumerationFlags fl

public DirectoryPath GetPidFileDirectory()
{
var directory = _environmentProvider.GetEnvironmentVariable("DOTNET_BUILD_PIDFILE_DIRECTORY");
var directory = _environmentProvider.GetEnvironmentVariable(PidFileDirectoryVariableName);
if (!string.IsNullOrEmpty(directory))
{
return new DirectoryPath(directory);
Expand All @@ -82,5 +86,22 @@ public DirectoryPath GetPidFileDirectory()
"pids",
"build"));
}

private RazorPidFile ReadRazorPidFile(FilePath path)
{
try
{
return RazorPidFile.Read(path, _fileSystem);
}
catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException)
{
_reporter.WriteLine(
string.Format(
LocalizableStrings.FailedToReadPidFile,
path.Value,
ex.Message).Yellow());
return null;
}
}
}
}
3 changes: 3 additions & 0 deletions src/dotnet/BuildServer/LocalizableStrings.resx
Expand Up @@ -129,4 +129,7 @@
<data name="ShutdownCommandFailed" xml:space="preserve">
<value>The shutdown command failed: {0}</value>
</data>
<data name="FailedToReadPidFile" xml:space="preserve">
<value>Failed to read pid file '{0}': {1}</value>
</data>
</root>
8 changes: 7 additions & 1 deletion src/dotnet/BuildServer/RazorPidFile.cs
Expand Up @@ -33,7 +33,13 @@ public static RazorPidFile Read(FilePath path, IFileSystem fileSystem = null)
{
fileSystem = fileSystem ?? FileSystemWrapper.Default;

using (var stream = fileSystem.File.OpenRead(path.Value))
using (var stream = fileSystem.File.OpenFile(
path.Value,
FileMode.Open,
FileAccess.Read,
FileShare.Write | FileShare.Delete,
4096,
FileOptions.None))
using (var reader = new StreamReader(stream, Encoding.UTF8))
{
if (!int.TryParse(reader.ReadLine(), out var processId))
Expand Down
5 changes: 5 additions & 0 deletions src/dotnet/BuildServer/xlf/LocalizableStrings.cs.xlf
Expand Up @@ -22,6 +22,11 @@
<target state="new">The shutdown command failed: {0}</target>
<note />
</trans-unit>
<trans-unit id="FailedToReadPidFile">
<source>Failed to read pid file '{0}': {1}</source>
<target state="new">Failed to read pid file '{0}': {1}</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
5 changes: 5 additions & 0 deletions src/dotnet/BuildServer/xlf/LocalizableStrings.de.xlf
Expand Up @@ -22,6 +22,11 @@
<target state="new">The shutdown command failed: {0}</target>
<note />
</trans-unit>
<trans-unit id="FailedToReadPidFile">
<source>Failed to read pid file '{0}': {1}</source>
<target state="new">Failed to read pid file '{0}': {1}</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
5 changes: 5 additions & 0 deletions src/dotnet/BuildServer/xlf/LocalizableStrings.es.xlf
Expand Up @@ -22,6 +22,11 @@
<target state="new">The shutdown command failed: {0}</target>
<note />
</trans-unit>
<trans-unit id="FailedToReadPidFile">
<source>Failed to read pid file '{0}': {1}</source>
<target state="new">Failed to read pid file '{0}': {1}</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
5 changes: 5 additions & 0 deletions src/dotnet/BuildServer/xlf/LocalizableStrings.fr.xlf
Expand Up @@ -22,6 +22,11 @@
<target state="new">The shutdown command failed: {0}</target>
<note />
</trans-unit>
<trans-unit id="FailedToReadPidFile">
<source>Failed to read pid file '{0}': {1}</source>
<target state="new">Failed to read pid file '{0}': {1}</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
5 changes: 5 additions & 0 deletions src/dotnet/BuildServer/xlf/LocalizableStrings.it.xlf
Expand Up @@ -22,6 +22,11 @@
<target state="new">The shutdown command failed: {0}</target>
<note />
</trans-unit>
<trans-unit id="FailedToReadPidFile">
<source>Failed to read pid file '{0}': {1}</source>
<target state="new">Failed to read pid file '{0}': {1}</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
5 changes: 5 additions & 0 deletions src/dotnet/BuildServer/xlf/LocalizableStrings.ja.xlf
Expand Up @@ -22,6 +22,11 @@
<target state="new">The shutdown command failed: {0}</target>
<note />
</trans-unit>
<trans-unit id="FailedToReadPidFile">
<source>Failed to read pid file '{0}': {1}</source>
<target state="new">Failed to read pid file '{0}': {1}</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
5 changes: 5 additions & 0 deletions src/dotnet/BuildServer/xlf/LocalizableStrings.ko.xlf
Expand Up @@ -22,6 +22,11 @@
<target state="new">The shutdown command failed: {0}</target>
<note />
</trans-unit>
<trans-unit id="FailedToReadPidFile">
<source>Failed to read pid file '{0}': {1}</source>
<target state="new">Failed to read pid file '{0}': {1}</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
5 changes: 5 additions & 0 deletions src/dotnet/BuildServer/xlf/LocalizableStrings.pl.xlf
Expand Up @@ -22,6 +22,11 @@
<target state="new">The shutdown command failed: {0}</target>
<note />
</trans-unit>
<trans-unit id="FailedToReadPidFile">
<source>Failed to read pid file '{0}': {1}</source>
<target state="new">Failed to read pid file '{0}': {1}</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
5 changes: 5 additions & 0 deletions src/dotnet/BuildServer/xlf/LocalizableStrings.pt-BR.xlf
Expand Up @@ -22,6 +22,11 @@
<target state="new">The shutdown command failed: {0}</target>
<note />
</trans-unit>
<trans-unit id="FailedToReadPidFile">
<source>Failed to read pid file '{0}': {1}</source>
<target state="new">Failed to read pid file '{0}': {1}</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
5 changes: 5 additions & 0 deletions src/dotnet/BuildServer/xlf/LocalizableStrings.ru.xlf
Expand Up @@ -22,6 +22,11 @@
<target state="new">The shutdown command failed: {0}</target>
<note />
</trans-unit>
<trans-unit id="FailedToReadPidFile">
<source>Failed to read pid file '{0}': {1}</source>
<target state="new">Failed to read pid file '{0}': {1}</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
5 changes: 5 additions & 0 deletions src/dotnet/BuildServer/xlf/LocalizableStrings.tr.xlf
Expand Up @@ -22,6 +22,11 @@
<target state="new">The shutdown command failed: {0}</target>
<note />
</trans-unit>
<trans-unit id="FailedToReadPidFile">
<source>Failed to read pid file '{0}': {1}</source>
<target state="new">Failed to read pid file '{0}': {1}</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
5 changes: 5 additions & 0 deletions src/dotnet/BuildServer/xlf/LocalizableStrings.zh-Hans.xlf
Expand Up @@ -22,6 +22,11 @@
<target state="new">The shutdown command failed: {0}</target>
<note />
</trans-unit>
<trans-unit id="FailedToReadPidFile">
<source>Failed to read pid file '{0}': {1}</source>
<target state="new">Failed to read pid file '{0}': {1}</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
5 changes: 5 additions & 0 deletions src/dotnet/BuildServer/xlf/LocalizableStrings.zh-Hant.xlf
Expand Up @@ -22,6 +22,11 @@
<target state="new">The shutdown command failed: {0}</target>
<note />
</trans-unit>
<trans-unit id="FailedToReadPidFile">
<source>Failed to read pid file '{0}': {1}</source>
<target state="new">Failed to read pid file '{0}': {1}</target>
<note />
</trans-unit>
</body>
</file>
</xliff>
@@ -0,0 +1,20 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Microsoft.DotNet.Cli.Utils;

namespace Microsoft.DotNet.Tools.Test.Utilities
{
public sealed class BuildServerCommand : DotnetCommand
{
public override CommandResult Execute(string args = "")
{
return base.Execute($"build-server {args}");
}

public override CommandResult ExecuteWithCapturedOutput(string args = "")
{
return base.ExecuteWithCapturedOutput($"build-server {args}");
}
}
}
Expand Up @@ -94,6 +94,11 @@ public Stream OpenRead(string path)
int bufferSize,
FileOptions fileOptions)
{
if (fileMode == FileMode.Open && fileAccess == FileAccess.Read)
{
return OpenRead(path);
}

throw new NotImplementedException();
}

Expand Down

0 comments on commit b2b3947

Please sign in to comment.