From 02e63c8cbe6125071942eba194dfa6b4be205233 Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Thu, 16 Jan 2025 17:24:16 -0800 Subject: [PATCH] Prevent 503s from IIS after IISNativeApplication gets finalized --- src/Servers/IIS/IIS/src/Core/IISHttpServer.cs | 5 ++-- .../IIS/IIS/src/Core/IISNativeApplication.cs | 28 +++++++++---------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/Servers/IIS/IIS/src/Core/IISHttpServer.cs b/src/Servers/IIS/IIS/src/Core/IISHttpServer.cs index 3390478626a5..68a634ebb21e 100644 --- a/src/Servers/IIS/IIS/src/Core/IISHttpServer.cs +++ b/src/Servers/IIS/IIS/src/Core/IISHttpServer.cs @@ -132,7 +132,7 @@ public void Dispose() _disposed = true; // Block any more calls into managed from native as we are unloading. - _nativeApplication.StopCallsIntoManaged(); + _nativeApplication.Stop(); _shutdownSignal.TrySetResult(); if (_httpServerHandle.IsAllocated) @@ -141,7 +141,6 @@ public void Dispose() } _memoryPool.Dispose(); - _nativeApplication.Dispose(); } [UnmanagedCallersOnly] @@ -261,7 +260,7 @@ private static void OnRequestsDrained(IntPtr serverContext) return; } - server._nativeApplication.StopCallsIntoManaged(); + server._nativeApplication.Stop(); server._shutdownSignal.TrySetResult(); server._cancellationTokenRegistration.Dispose(); } diff --git a/src/Servers/IIS/IIS/src/Core/IISNativeApplication.cs b/src/Servers/IIS/IIS/src/Core/IISNativeApplication.cs index a031f50aebf7..b38f2068bd50 100644 --- a/src/Servers/IIS/IIS/src/Core/IISNativeApplication.cs +++ b/src/Servers/IIS/IIS/src/Core/IISNativeApplication.cs @@ -6,6 +6,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core; internal sealed class IISNativeApplication { private readonly NativeSafeHandle _nativeApplication; + private bool _hasRegisteredCallbacks; private readonly object _sync = new object(); public IISNativeApplication(NativeSafeHandle nativeApplication) @@ -24,14 +25,22 @@ public void StopIncomingRequests() } } - public void StopCallsIntoManaged() + public void Stop() { lock (_sync) { - if (!_nativeApplication.IsInvalid) + if (_nativeApplication.IsInvalid) + { + return; + } + + if (_hasRegisteredCallbacks) { NativeMethods.HttpStopCallsIntoManaged(_nativeApplication); } + + _nativeApplication.Dispose(); + GC.SuppressFinalize(this); } } @@ -44,6 +53,8 @@ public unsafe void RegisterCallbacks( IntPtr pvRequestContext, IntPtr pvShutdownContext) { + _hasRegisteredCallbacks = true; + NativeMethods.HttpRegisterCallbacks( _nativeApplication, requestCallback, @@ -55,20 +66,9 @@ public unsafe void RegisterCallbacks( pvShutdownContext); } - public void Dispose() - { - lock (_sync) - { - GC.SuppressFinalize(this); - - // Don't need to await here because pinvokes should never been called after disposing the safe handle. - _nativeApplication.Dispose(); - } - } - ~IISNativeApplication() { // If this finalize is invoked, try our best to block all calls into managed. - StopCallsIntoManaged(); + Stop(); } }