Skip to content

Commit

Permalink
Clean up Razor Server pid file if the path doesn't exist (#29029)
Browse files Browse the repository at this point in the history
When the server path in the pid file didn't exist we'd hit an error:

```
The shutdown command failed: The application to execute does not exist
```

This can happen when the file wasn't cleaned up and the SDK was uninstalled in the meantime.
Ensure we delete the pid file in that case and don't error.

Fixes #10573
  • Loading branch information
akoeplinger authored Nov 15, 2022
1 parent fc06e69 commit a95dd63
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 4 deletions.
13 changes: 13 additions & 0 deletions src/Cli/dotnet/BuildServer/RazorServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ public RazorServer(

public void Shutdown()
{
if(!_fileSystem.File.Exists(PidFile.ServerPath.Value))
{
// The razor server path doesn't exist anymore so trying to shut it down would fail
// Ensure the pid file is cleaned up so we don't try to shut it down again
DeletePidFile();
return;
}

var command = _commandFactory
.Create(
"exec",
Expand All @@ -60,6 +68,11 @@ public void Shutdown()

// After a successful shutdown, ensure the pid file is deleted
// If the pid file was left behind due to a rude exit, this ensures we don't try to shut it down again
DeletePidFile();
}

void DeletePidFile()
{
try
{
if (_fileSystem.File.Exists(PidFile.Path.Value))
Expand Down
50 changes: 46 additions & 4 deletions src/Tests/dotnet.Tests/BuildServerTests/RazorServerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using FluentAssertions;
Expand Down Expand Up @@ -31,14 +32,16 @@ public void GivenAFailedShutdownCommandItThrows()
string pidDirectory = Path.GetFullPath("var/pids/build");
string pidFilePath = Path.Combine(pidDirectory, $"{RazorPidFile.FilePrefix}{ProcessId}");

var serverPath = Path.GetFullPath("path/to/rzc.dll");

var fileSystemMock = new FileSystemMockBuilder()
.AddFile(pidFilePath, "")
.AddFile(serverPath, "")
.UseCurrentSystemTemporaryDirectory()
.Build();

fileSystemMock.File.Exists(pidFilePath).Should().BeTrue();

var serverPath = Path.Combine(fileSystemMock.Directory.CreateTemporaryDirectory().DirectoryPath, "path/to/rzc.dll");
fileSystemMock.File.Exists(serverPath).Should().BeTrue();

var server = new RazorServer(
pidFile: new RazorPidFile(
Expand Down Expand Up @@ -68,14 +71,16 @@ public void GivenASuccessfulShutdownItDoesNotThrow()
string pidDirectory = Path.GetFullPath("var/pids/build");
string pidFilePath = Path.Combine(pidDirectory, $"{RazorPidFile.FilePrefix}{ProcessId}");

var serverPath = Path.GetFullPath("path/to/rzc.dll");

var fileSystemMock = new FileSystemMockBuilder()
.AddFile(pidFilePath, "")
.AddFile(serverPath, "")
.UseCurrentSystemTemporaryDirectory()
.Build();

fileSystemMock.File.Exists(pidFilePath).Should().BeTrue();

var serverPath = Path.Combine(fileSystemMock.Directory.CreateTemporaryDirectory().DirectoryPath, "path/to/rzc.dll");
fileSystemMock.File.Exists(serverPath).Should().BeTrue();

var server = new RazorServer(
pidFile: new RazorPidFile(
Expand All @@ -91,6 +96,43 @@ public void GivenASuccessfulShutdownItDoesNotThrow()
fileSystemMock.File.Exists(pidFilePath).Should().BeFalse();
}

[Fact]
public void GivenANonExistingRazorServerPathItDeletesPidFileAndDoesNotThrow()
{
const int ProcessId = 1234;
const string PipeName = "some-pipe-name";

string pidDirectory = Path.GetFullPath("var/pids/build");
string pidFilePath = Path.Combine(pidDirectory, $"{RazorPidFile.FilePrefix}{ProcessId}");

var serverPath = Path.GetFullPath("path/to/rzc.dll");

var fileSystemMock = new FileSystemMockBuilder()
.AddFile(pidFilePath, "")
.UseCurrentSystemTemporaryDirectory()
.Build();

fileSystemMock.File.Exists(pidFilePath).Should().BeTrue();
fileSystemMock.File.Exists(serverPath).Should().BeFalse();

var commandFactoryMock = CreateCommandFactoryMock(serverPath, PipeName);
var server = new RazorServer(
pidFile: new RazorPidFile(
path: new FilePath(pidFilePath),
processId: ProcessId,
serverPath: new FilePath(serverPath),
pipeName: PipeName),
commandFactory: commandFactoryMock.Object,
fileSystem: fileSystemMock);

Action a = () => server.Shutdown();

a.Should().NotThrow();
commandFactoryMock.Verify(c => c.Create(It.IsAny<string>(), It.IsAny<IEnumerable<string>>(), It.IsAny<NuGetFramework>(), It.IsAny<string>()), Times.Never);

fileSystemMock.File.Exists(pidFilePath).Should().BeFalse();
}

private Mock<ICommandFactory> CreateCommandFactoryMock(string serverPath, string pipeName, int exitCode = 0, string stdErr = "")
{
var commandMock = new Mock<ICommand>(MockBehavior.Strict);
Expand Down

0 comments on commit a95dd63

Please sign in to comment.