fix: restart relaunches correctly when the server path contains a space (#2704)

`Core.DoKill(true)` built the relaunch command line by putting the assembly path into a raw argument string without quotes, so `dotnet` split it at the first space. That breaks `restart`, `AutoRestart` and `CrashGuard` recovery for any server installed under a path with a space.

- Pass the assembly path through `ProcessStartInfo.ArgumentList`, which quotes it.
- Relaunch through the host that started the process (`Environment.ProcessPath`): the `ModernUO` apphost runs directly, and `dotnet` gets the assembly path. Before this, a server started from the apphost came back under `dotnet`.
- Use one code path on all platforms. `UseShellExecute = true` on Unix made no difference for a program found on PATH.

This doesn't fix the second half of #2700, where the relaunched server loses the console (and gets killed under systemd or Docker). That comes from the server spawning a copy of itself and exiting, and a follow-up PR will add an opt-in restart exit code for a supervisor to act on.

**Testing:** relaunched from a directory with spaces, started both through `dotnet x.dll` and through the apphost, on Windows. The old code fails there with the error from the issue.
This commit is contained in:
Kamron Batman 2026-10-13 21:13:34 -07:00 • committed by GitHub
parent 6c49038230
commit 577a4da60c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -473,22 +473,17 @@ public static class Core
try try
{ {
logger.Information("Restarting"); logger.Information("Restarting");
if (IsWindows)
{
using var process = Process.Start("dotnet", $"{ApplicationAssembly.Location}");
}
else
{
using var process = new Process();
process.StartInfo = new ProcessStartInfo
{
FileName = "dotnet",
Arguments = $"{ApplicationAssembly.Location}",
UseShellExecute = true
};
process.Start(); // Relaunch through whichever host started us: the apphost (ModernUO.exe) runs directly,
// `dotnet ModernUO.dll` needs the assembly path. ArgumentList quotes paths with spaces.
var hostPath = Environment.ProcessPath ?? "dotnet";
var startInfo = new ProcessStartInfo(hostPath) { UseShellExecute = false };
if (Path.GetFileNameWithoutExtension(hostPath).Equals("dotnet", StringComparison.OrdinalIgnoreCase))
{
startInfo.ArgumentList.Add(ApplicationAssembly.Location);
} }
using var process = Process.Start(startInfo);
logger.Information("Restart done"); logger.Information("Restart done");
} }
catch (Exception e) catch (Exception e)