From 0b1bffa5c8a4bffa09f6ad0cd46d170313bbf5fa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 17 Jul 2025 16:30:06 +0000 Subject: [PATCH 1/2] Initial plan From d1dff6e30726b0b5da08730e76f4bafb72e19407 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 17 Jul 2025 16:42:34 +0000 Subject: [PATCH 2/2] Implement POSIX signal handling for DevServer Co-authored-by: maraf <10020471+maraf@users.noreply.github.com> --- .../WebAssembly/DevServer/src/Program.cs | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/src/Components/WebAssembly/DevServer/src/Program.cs b/src/Components/WebAssembly/DevServer/src/Program.cs index 0a52b2bfb1d0..b3eb7e3167dc 100644 --- a/src/Components/WebAssembly/DevServer/src/Program.cs +++ b/src/Components/WebAssembly/DevServer/src/Program.cs @@ -1,7 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.InteropServices; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using DevServerProgram = Microsoft.AspNetCore.Components.WebAssembly.DevServer.Server.Program; @@ -11,7 +13,62 @@ internal sealed class Program { static int Main(string[] args) { - DevServerProgram.BuildWebHost(args).Run(); + var host = DevServerProgram.BuildWebHost(args); + + // Register POSIX signal handlers for graceful shutdown on Unix systems + if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS()) + { + using var lifetime = new DevServerLifetime(host.Services.GetRequiredService()); + host.Run(); + } + else + { + host.Run(); + } + return 0; } } + +internal sealed class DevServerLifetime : IDisposable +{ + private readonly IHostApplicationLifetime _applicationLifetime; + private readonly PosixSignalRegistration _sigIntRegistration; + private readonly PosixSignalRegistration _sigQuitRegistration; + private readonly PosixSignalRegistration _sigTermRegistration; + + private bool _disposed; + + public DevServerLifetime(IHostApplicationLifetime applicationLifetime) + { + _applicationLifetime = applicationLifetime; + + Action handler = HandlePosixSignal; + _sigIntRegistration = PosixSignalRegistration.Create(PosixSignal.SIGINT, handler); + _sigQuitRegistration = PosixSignalRegistration.Create(PosixSignal.SIGQUIT, handler); + _sigTermRegistration = PosixSignalRegistration.Create(PosixSignal.SIGTERM, handler); + } + + public void Dispose() + { + if (_disposed) + { + return; + } + + _disposed = true; + + _sigIntRegistration.Dispose(); + _sigQuitRegistration.Dispose(); + _sigTermRegistration.Dispose(); + } + + private void HandlePosixSignal(PosixSignalContext context) + { + // Request graceful shutdown + _applicationLifetime.StopApplication(); + + // Don't terminate the process immediately, wait for the application to exit gracefully. + context.Cancel = true; + } +}