[3.1.x] Allow external startup hooks (#17116)
This commit is contained in:
parent
e1e6bf8587
commit
c31f51e5c7
|
|
@ -47,6 +47,7 @@ void HostFxr::Load(HMODULE moduleHandle)
|
|||
m_corehost_set_error_writer_fn = ModuleHelpers::GetKnownProcAddress<corehost_set_error_writer_fn>(moduleHandle, "hostfxr_set_error_writer", /* optional */ true);
|
||||
m_hostfxr_initialize_for_dotnet_commandline_fn = ModuleHelpers::GetKnownProcAddress<hostfxr_initialize_for_dotnet_runtime_fn>(moduleHandle, "hostfxr_initialize_for_dotnet_command_line", /* optional */ true);
|
||||
m_hostfxr_set_runtime_property_value_fn = ModuleHelpers::GetKnownProcAddress<hostfxr_set_runtime_property_value_fn>(moduleHandle, "hostfxr_set_runtime_property_value", /* optional */ true);
|
||||
m_hostfxr_get_runtime_property_value_fn = ModuleHelpers::GetKnownProcAddress<hostfxr_get_runtime_property_value_fn>(moduleHandle, "hostfxr_get_runtime_property_value", /* optional */ true);
|
||||
m_hostfxr_run_app_fn = ModuleHelpers::GetKnownProcAddress<hostfxr_run_app_fn>(moduleHandle, "hostfxr_run_app", /* optional */ true);
|
||||
m_hostfxr_close_fn = ModuleHelpers::GetKnownProcAddress<hostfxr_close_fn>(moduleHandle, "hostfxr_close", /* optional */ true);
|
||||
}
|
||||
|
|
@ -164,6 +165,15 @@ int HostFxr::SetRuntimePropertyValue(PCWSTR name, PCWSTR value) const noexcept
|
|||
return 0;
|
||||
}
|
||||
|
||||
int HostFxr::GetRuntimePropertyValue(PCWSTR name, PWSTR* value) const noexcept
|
||||
{
|
||||
if (m_host_context_handle != nullptr && m_hostfxr_get_runtime_property_value_fn != nullptr)
|
||||
{
|
||||
return m_hostfxr_get_runtime_property_value_fn(m_host_context_handle, name, value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HostFxr::Close() const noexcept
|
||||
{
|
||||
if (m_host_context_handle != nullptr && m_hostfxr_close_fn != nullptr)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ typedef void(*corehost_error_writer_fn) (const WCHAR* message);
|
|||
typedef corehost_error_writer_fn(*corehost_set_error_writer_fn) (corehost_error_writer_fn error_writer);
|
||||
typedef int(*hostfxr_initialize_for_dotnet_runtime_fn)(int argc, const PCWSTR* argv, hostfxr_initialize_parameters* parameters, void* const* host_context_handle);
|
||||
typedef int(*hostfxr_set_runtime_property_value_fn)(void* host_context_handle, PCWSTR name, PCWSTR value);
|
||||
typedef int(*hostfxr_get_runtime_property_value_fn)(void* host_context_handle, PCWSTR name, PWSTR* value);
|
||||
typedef int(*hostfxr_run_app_fn)(void* host_context_handle);
|
||||
typedef int(*hostfxr_close_fn)(void* hostfxr_context_handle);
|
||||
|
||||
|
|
@ -73,6 +74,7 @@ public:
|
|||
|
||||
HostFxrErrorRedirector RedirectOutput(RedirectionOutput* writer) const noexcept;
|
||||
int SetRuntimePropertyValue(PCWSTR name, PCWSTR value) const noexcept;
|
||||
int GetRuntimePropertyValue(PCWSTR name, PWSTR* value) const noexcept;
|
||||
int InitializeForApp(int argc, PCWSTR* argv, const std::wstring& m_dotnetExeKnownLocation) const noexcept;
|
||||
void Close() const noexcept;
|
||||
|
||||
|
|
@ -82,6 +84,7 @@ private:
|
|||
hostfxr_get_native_search_directories_fn m_hostfxr_get_native_search_directories_fn;
|
||||
hostfxr_initialize_for_dotnet_runtime_fn m_hostfxr_initialize_for_dotnet_commandline_fn;
|
||||
hostfxr_set_runtime_property_value_fn m_hostfxr_set_runtime_property_value_fn;
|
||||
hostfxr_get_runtime_property_value_fn m_hostfxr_get_runtime_property_value_fn;
|
||||
hostfxr_run_app_fn m_hostfxr_run_app_fn;
|
||||
corehost_set_error_writer_fn m_corehost_set_error_writer_fn;
|
||||
hostfxr_close_fn m_hostfxr_close_fn;
|
||||
|
|
|
|||
|
|
@ -252,7 +252,20 @@ IN_PROCESS_APPLICATION::ExecuteApplication()
|
|||
|
||||
if (m_pConfig->QueryCallStartupHook())
|
||||
{
|
||||
RETURN_IF_NOT_ZERO(context->m_hostFxr.SetRuntimePropertyValue(DOTNETCORE_STARTUP_HOOK, ASPNETCORE_STARTUP_ASSEMBLY));
|
||||
PWSTR startupHookValue = NULL;
|
||||
// Will get property not found if the enviroment variable isn't set.
|
||||
context->m_hostFxr.GetRuntimePropertyValue(DOTNETCORE_STARTUP_HOOK, &startupHookValue);
|
||||
|
||||
if (startupHookValue == NULL)
|
||||
{
|
||||
RETURN_IF_NOT_ZERO(context->m_hostFxr.SetRuntimePropertyValue(DOTNETCORE_STARTUP_HOOK, ASPNETCORE_STARTUP_ASSEMBLY));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::wstring startupHook(startupHookValue);
|
||||
startupHook.append(L";").append(ASPNETCORE_STARTUP_ASSEMBLY);
|
||||
RETURN_IF_NOT_ZERO(context->m_hostFxr.SetRuntimePropertyValue(DOTNETCORE_STARTUP_HOOK, startupHook.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_IF_NOT_ZERO(context->m_hostFxr.SetRuntimePropertyValue(DOTNETCORE_USE_ENTRYPOINT_FILTER, L"1"));
|
||||
|
|
|
|||
|
|
@ -817,6 +817,42 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.InProcess
|
|||
VerifyDotnetRuntimeEventLog(deploymentResult);
|
||||
}
|
||||
|
||||
|
||||
[ConditionalFact]
|
||||
[RequiresNewHandler]
|
||||
public async Task CanAddCustomStartupHook()
|
||||
{
|
||||
var deploymentParameters = Fixture.GetBaseDeploymentParameters();
|
||||
|
||||
// Deployment parameters by default set ASPNETCORE_DETAILEDERRORS to true
|
||||
deploymentParameters.WebConfigBasedEnvironmentVariables["DOTNET_STARTUP_HOOKS"] = "InProcessWebSite";
|
||||
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
var result = await deploymentResult.HttpClient.GetAsync("/StartupHook");
|
||||
var content = await result.Content.ReadAsStringAsync();
|
||||
Assert.Equal("True", content);
|
||||
|
||||
StopServer();
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[RequiresNewHandler]
|
||||
public async Task CanAddCustomStartupHookWhenIISOneIsDisabled()
|
||||
{
|
||||
var deploymentParameters = Fixture.GetBaseDeploymentParameters();
|
||||
|
||||
// Deployment parameters by default set ASPNETCORE_DETAILEDERRORS to true
|
||||
deploymentParameters.WebConfigBasedEnvironmentVariables["DOTNET_STARTUP_HOOKS"] = "InProcessWebSite";
|
||||
deploymentParameters.HandlerSettings["callStartupHook"] = "false";
|
||||
|
||||
var deploymentResult = await DeployAsync(deploymentParameters);
|
||||
var result = await deploymentResult.HttpClient.GetAsync("/StartupHook");
|
||||
var content = await result.Content.ReadAsStringAsync();
|
||||
Assert.Equal("True", content);
|
||||
|
||||
StopServer();
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[RequiresNewHandler]
|
||||
public async Task StackOverflowIsAvoidedBySettingLargerStack()
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ namespace TestSite
|
|||
{
|
||||
public partial class Startup
|
||||
{
|
||||
public static bool StartupHookCalled;
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
if (Environment.GetEnvironmentVariable("ENABLE_HTTPS_REDIRECTION") != null)
|
||||
|
|
@ -900,6 +902,11 @@ namespace TestSite
|
|||
RecursiveFunction(i - 1);
|
||||
}
|
||||
|
||||
private async Task StartupHook(HttpContext ctx)
|
||||
{
|
||||
await ctx.Response.WriteAsync(StartupHookCalled.ToString());
|
||||
}
|
||||
|
||||
private async Task GetServerVariableStress(HttpContext ctx)
|
||||
{
|
||||
// This test simulates the scenario where native Flush call is being
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
using TestSite;
|
||||
|
||||
internal class StartupHook
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
Startup.StartupHookCalled = true;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue