Просмотр исходного кода

Add an event log message when loading hostfxr fails (#6670)

Pavel Krymets 7 лет назад
Родитель
Сommit
41c1490468

+ 3 - 5
src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp

@@ -214,9 +214,7 @@ try
     DWORD          dwBufferSize = s_initialGetNativeSearchDirectoriesBufferSize;
     DWORD          dwRequiredBufferSize = 0;
 
-    RETURN_LAST_ERROR_IF_NULL(m_hHostFxrDll = LoadLibraryW(hostfxrOptions.GetHostFxrLocation().c_str()));
-
-    auto const hostFxr = HostFxr::CreateFromLoadedModule();
+    m_hHostFxrDll.Load(hostfxrOptions.GetHostFxrLocation());
 
     {
         auto redirectionOutput = LoggingHelpers::CreateOutputs(
@@ -227,7 +225,7 @@ try
             );
 
         StandardStreamRedirection stdOutRedirection(*redirectionOutput.get(), m_pServer.IsCommandLineLaunch());
-        auto hostFxrErrorRedirection = hostFxr.RedirectOutput(redirectionOutput.get());
+        auto hostFxrErrorRedirection = m_hHostFxrDll.RedirectOutput(redirectionOutput.get());
 
         struNativeSearchPaths.resize(dwBufferSize);
         while (TRUE)
@@ -237,7 +235,7 @@ try
 
             hostfxrOptions.GetArguments(hostfxrArgc, hostfxrArgv);
 
-            const auto intHostFxrExitCode = hostFxr.GetNativeSearchDirectories(
+            const auto intHostFxrExitCode = m_hHostFxrDll.GetNativeSearchDirectories(
                 hostfxrArgc,
                 hostfxrArgv.get(),
                 struNativeSearchPaths.data(),

+ 2 - 1
src/Servers/IIS/AspNetCoreModuleV2/AspNetCore/HandlerResolver.h

@@ -10,6 +10,7 @@
 #include "HandleWrapper.h"
 #include "ApplicationFactory.h"
 #include "RedirectionOutput.h"
+#include "HostFxr.h"
 
 class HandlerResolver
 {
@@ -35,7 +36,7 @@ private:
     SRWLOCK      m_requestHandlerLoadLock {};
     std::wstring m_loadedApplicationId;
     APP_HOSTING_MODEL m_loadedApplicationHostingModel;
-    HandleWrapper<ModuleHandleTraits> m_hHostFxrDll;
+    HostFxr m_hHostFxrDll;
 
     static const PCWSTR          s_pwzAspnetcoreInProcessRequestHandlerName;
     static const PCWSTR          s_pwzAspnetcoreOutOfProcessRequestHandlerName;

+ 49 - 18
src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxr.cpp

@@ -30,41 +30,72 @@ void HostFxrErrorRedirector::HostFxrErrorRedirectorCallback(const WCHAR* message
     m_writeFunction->Append(std::wstring(message) + L"\r\n");
 }
 
-int HostFxr::Main(DWORD argc, const PCWSTR* argv) const noexcept(false)
-{
-    return m_hostfxr_main_fn(argc, argv);
-}
 
-int HostFxr::GetNativeSearchDirectories(INT argc, const PCWSTR* argv, PWSTR buffer, DWORD buffer_size, DWORD* required_buffer_size) const noexcept
+void HostFxr::Load()
 {
-    return m_hostfxr_get_native_search_directories_fn(argc, argv, buffer, buffer_size, required_buffer_size);
+    HMODULE hModule;
+    THROW_LAST_ERROR_IF(!GetModuleHandleEx(0, L"hostfxr.dll", &hModule));
+    Load(hModule);
 }
 
-HostFxrErrorRedirector HostFxr::RedirectOutput(RedirectionOutput* writer) const noexcept
+void HostFxr::Load(HMODULE moduleHandle)
 {
-    return HostFxrErrorRedirector(m_corehost_set_error_writer_fn, writer);
+    m_hHostFxrDll = moduleHandle;
+    try
+    {
+        m_hostfxr_main_fn = ModuleHelpers::GetKnownProcAddress<hostfxr_main_fn>(moduleHandle, "hostfxr_main");
+        m_hostfxr_get_native_search_directories_fn = ModuleHelpers::GetKnownProcAddress<hostfxr_get_native_search_directories_fn>(moduleHandle, "hostfxr_get_native_search_directories");
+        m_corehost_set_error_writer_fn = ModuleHelpers::GetKnownProcAddress<corehost_set_error_writer_fn>(moduleHandle, "hostfxr_set_error_writer", /* optional */ true);
+    }
+    catch (...)
+    {
+        EventLog::Error(
+            ASPNETCORE_EVENT_GENERAL_ERROR,
+            ASPNETCORE_EVENT_HOSTFXR_DLL_INVALID_VERSION_MSG,
+            ModuleHelpers::GetModuleFileNameValue(moduleHandle).c_str()
+        );
+
+        throw;
+    }
 }
 
-HostFxr HostFxr::CreateFromLoadedModule()
-{
-    HMODULE hModule;
-    THROW_LAST_ERROR_IF_NULL(hModule = GetModuleHandle(L"hostfxr.dll"));
 
+void HostFxr::Load(const std::wstring& location)
+{
     try
     {
-        return HostFxr(
-            ModuleHelpers::GetKnownProcAddress<hostfxr_main_fn>(hModule, "hostfxr_main"),
-            ModuleHelpers::GetKnownProcAddress<hostfxr_get_native_search_directories_fn>(hModule, "hostfxr_get_native_search_directories"),
-            ModuleHelpers::GetKnownProcAddress<corehost_set_error_writer_fn>(hModule, "hostfxr_set_error_writer", /* optional */ true));
+        HMODULE hModule;
+        THROW_LAST_ERROR_IF_NULL(hModule = LoadLibraryW(location.c_str()));
+        Load(hModule);
     }
     catch (...)
     {
         EventLog::Error(
             ASPNETCORE_EVENT_GENERAL_ERROR,
-            ASPNETCORE_EVENT_HOSTFXR_DLL_INVALID_VERSION_MSG,
-            ModuleHelpers::GetModuleFileNameValue(hModule).c_str()
+            ASPNETCORE_EVENT_HOSTFXR_DLL_UNABLE_TO_LOAD_MSG,
+            location.c_str()
         );
 
         throw;
     }
 }
+
+void HostFxr::SetMain(hostfxr_main_fn hostfxr_main_fn)
+{
+    m_hostfxr_main_fn = hostfxr_main_fn;
+}
+
+int HostFxr::Main(DWORD argc, const PCWSTR* argv) const noexcept(false)
+{
+    return m_hostfxr_main_fn(argc, argv);
+}
+
+int HostFxr::GetNativeSearchDirectories(INT argc, const PCWSTR* argv, PWSTR buffer, DWORD buffer_size, DWORD* required_buffer_size) const noexcept
+{
+    return m_hostfxr_get_native_search_directories_fn(argc, argv, buffer, buffer_size, required_buffer_size);
+}
+
+HostFxrErrorRedirector HostFxr::RedirectOutput(RedirectionOutput* writer) const noexcept
+{
+    return HostFxrErrorRedirector(m_corehost_set_error_writer_fn, writer);
+}

+ 12 - 4
src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxr.h

@@ -26,9 +26,13 @@ private:
     static inline thread_local RedirectionOutput* m_writeFunction;
 };
 
-class HostFxr
+class HostFxr: NonCopyable
 {
 public:
+    HostFxr() : HostFxr(nullptr, nullptr, nullptr)
+    {
+    }
+
     HostFxr(
         hostfxr_main_fn hostfxr_main_fn,
         hostfxr_get_native_search_directories_fn hostfxr_get_native_search_directories_fn,
@@ -39,18 +43,22 @@ public:
     {
     }
 
+    void Load();
+    void Load(HMODULE moduleHandle);
+    void Load(const std::wstring& location);
+
     ~HostFxr() = default;
 
+    void SetMain(hostfxr_main_fn hostfxr_main_fn);
+
     int Main(DWORD argc, CONST PCWSTR* argv) const noexcept(false);
 
     int GetNativeSearchDirectories(INT argc, CONST PCWSTR* argv, PWSTR buffer, DWORD buffer_size, DWORD* required_buffer_size) const noexcept;
 
     HostFxrErrorRedirector RedirectOutput(RedirectionOutput* writer) const noexcept;
 
-    static
-    HostFxr CreateFromLoadedModule();
-
 private:
+    HandleWrapper<ModuleHandleTraits> m_hHostFxrDll;
     hostfxr_main_fn m_hostfxr_main_fn;
     hostfxr_get_native_search_directories_fn m_hostfxr_get_native_search_directories_fn;
     corehost_set_error_writer_fn m_corehost_set_error_writer_fn;

+ 1 - 0
src/Servers/IIS/AspNetCoreModuleV2/CommonLib/resources.h

@@ -39,6 +39,7 @@
 #define ASPNETCORE_EVENT_RECYCLE_FAILURE_CONFIGURATION_MSG   L"Failed to recycle application due to a configuration change at '%s'. Recycling worker process."
 #define ASPNETCORE_EVENT_MODULE_DISABLED_MSG                 L"AspNetCore Module is disabled"
 #define ASPNETCORE_EVENT_HOSTFXR_DLL_INVALID_VERSION_MSG     L"Hostfxr version used does not support 'hostfxr_get_native_search_directories', update the version of hostfxr to a higher version. Path to hostfxr: '%s'."
+#define ASPNETCORE_EVENT_HOSTFXR_DLL_UNABLE_TO_LOAD_MSG      L"Unable to load '%s'. This might be caused by a bitness mismatch between IIS application pool and published application."
 #define ASPNETCORE_EVENT_HOSTFXR_FAILURE_MSG                 L"Invoking hostfxr to find the inprocess request handler failed without finding any native dependencies. This most likely means the app is misconfigured, please check the versions of Microsoft.NetCore.App and Microsoft.AspNetCore.App that are targeted by the application and are installed on the machine."
 #define ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION_MSG      L"Application '%s' with physical root '%s' hit unexpected managed exception, exception code = '0x%x'. Please check the stderr logs for more information."
 #define ASPNETCORE_EVENT_INPROCESS_THREAD_EXCEPTION_STDOUT_MSG L"Application '%s' with physical root '%s' hit unexpected managed exception, exception code = '0x%x'. Last 4KB characters of captured stdout and stderr logs:\r\n%s"

+ 2 - 2
src/Servers/IIS/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp

@@ -189,11 +189,11 @@ IN_PROCESS_APPLICATION::ExecuteApplication()
 
             hostFxrResolutionResult->GetArguments(context->m_argc, context->m_argv);
             THROW_IF_FAILED(SetEnvironmentVariablesOnWorkerProcess());
-            context->m_hostFxr = HostFxr::CreateFromLoadedModule();
+            context->m_hostFxr.Load();
         }
         else
         {
-            context->m_hostFxr = HostFxr(s_fMainCallback, nullptr, nullptr);
+            context->m_hostFxr.SetMain(s_fMainCallback);
         }
 
         // There can only ever be a single instance of .NET Core

+ 15 - 1
src/Servers/IIS/IIS/test/Common.FunctionalTests/Inprocess/StartupTests.cs

@@ -257,7 +257,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
         }
 
         [ConditionalFact]
-        public async Task RemoveHostfxrFromApp_InProcessHostfxrInvalid()
+        public async Task RemoveHostfxrFromApp_InProcessHostfxrAPIAbsent()
         {
             var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true);
             deploymentParameters.ApplicationType = ApplicationType.Standalone;
@@ -272,6 +272,20 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
             EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessHostfxrInvalid(deploymentResult), Logger);
         }
 
+        [ConditionalFact]
+        public async Task RemoveHostfxrFromApp_InProcessHostfxrLoadFailure()
+        {
+            var deploymentParameters = _fixture.GetBaseDeploymentParameters(_fixture.InProcessTestSite, publish: true);
+            deploymentParameters.ApplicationType = ApplicationType.Standalone;
+            var deploymentResult = await DeployAsync(deploymentParameters);
+
+            // We don't distinguish between load failure types so making dll empty should be enough
+            File.WriteAllText(Path.Combine(deploymentResult.ContentRoot, "hostfxr.dll"), "");
+            await AssertSiteFailsToStartWithInProcessStaticContent(deploymentResult);
+
+            EventLogHelpers.VerifyEventLogEvent(deploymentResult, EventLogHelpers.InProcessHostfxrUnableToLoad(deploymentResult), Logger);
+        }
+
         [ConditionalFact]
         public async Task TargedDifferenceSharedFramework_FailedToFindNativeDependencies()
         {

+ 5 - 0
src/Servers/IIS/IIS/test/Common.FunctionalTests/Utilities/EventLogHelpers.cs

@@ -185,6 +185,11 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
             return $"Hostfxr version used does not support 'hostfxr_get_native_search_directories', update the version of hostfxr to a higher version. Path to hostfxr: '(.*)'.";
         }
 
+        public static string InProcessHostfxrUnableToLoad(IISDeploymentResult deploymentResult)
+        {
+            return $"Unable to load '(.*)'. This might be caused by a bitness mismatch between IIS application pool and published application.";
+        }
+
         public static string InProcessFailedToFindNativeDependencies(IISDeploymentResult deploymentResult)
         {
             return "Invoking hostfxr to find the inprocess request handler failed without finding any native dependencies. " +