Start using runtime properties to set StartupHook and EntrypointFilter (#10121)

This commit is contained in:
Justin Kotalik 2019-06-05 09:01:05 -07:00 committed by GitHub
parent 5af8e170bc
commit 214ca07b6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 112 additions and 24 deletions

View File

@ -30,7 +30,6 @@ void HostFxrErrorRedirector::HostFxrErrorRedirectorCallback(const WCHAR* message
m_writeFunction->Append(std::wstring(message) + L"\r\n");
}
void HostFxr::Load()
{
HMODULE hModule;
@ -43,9 +42,12 @@ void HostFxr::Load(HMODULE moduleHandle)
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);
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_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);
}
catch (...)
{
@ -59,7 +61,6 @@ void HostFxr::Load(HMODULE moduleHandle)
}
}
void HostFxr::Load(const std::wstring& location)
{
try
@ -87,7 +88,14 @@ void HostFxr::SetMain(hostfxr_main_fn hostfxr_main_fn)
int HostFxr::Main(DWORD argc, const PCWSTR* argv) const noexcept(false)
{
return m_hostfxr_main_fn(argc, argv);
if (m_host_context_handle != nullptr && m_hostfxr_run_app_fn != nullptr)
{
return m_hostfxr_run_app_fn(m_host_context_handle);
}
else
{
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
@ -99,3 +107,62 @@ HostFxrErrorRedirector HostFxr::RedirectOutput(RedirectionOutput* writer) const
{
return HostFxrErrorRedirector(m_corehost_set_error_writer_fn, writer);
}
int HostFxr::InitializeForApp(int argc, PCWSTR* argv, const std::wstring& dotnetExe) const noexcept
{
if (m_hostfxr_initialize_for_dotnet_commandline_fn == nullptr || m_hostfxr_main_fn != nullptr)
{
return 0;
}
hostfxr_initialize_parameters params;
params.size = sizeof(hostfxr_initialize_parameters);
params.host_path = L"";
// Transformation occurs here rather than hostfxr arguments as hostfxr_get_native_directories still needs
// exe as the first argument.
if (!dotnetExe.empty())
{
// Portable application
// argv[0] = dotnet.exe
// argv[1] = app.dll
// argv[2] = rest of the args
std::filesystem::path dotnetExePath(dotnetExe);
auto dotnetFolderPath = dotnetExePath.parent_path();
params.dotnet_root = dotnetFolderPath.c_str();
RETURN_INT_IF_NOT_ZERO(m_hostfxr_initialize_for_dotnet_commandline_fn(argc - 1, &argv[1], &params, &m_host_context_handle));
}
else
{
// Standalone application
// argv[0] = app.exe
// argv[1] = rest of the args
params.dotnet_root = L"";
std::filesystem::path applicationPath(argv[0]);
applicationPath.replace_extension(".dll");
argv[0] = applicationPath.c_str();
RETURN_INT_IF_NOT_ZERO(m_hostfxr_initialize_for_dotnet_commandline_fn(argc, argv, &params, &m_host_context_handle));
}
return 0;
}
int HostFxr::SetRuntimePropertyValue(PCWSTR name, PCWSTR value) const noexcept
{
if (m_host_context_handle != nullptr && m_hostfxr_set_runtime_property_value_fn != nullptr)
{
return m_hostfxr_set_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)
{
m_hostfxr_close_fn(m_host_context_handle);
}
}

View File

@ -7,10 +7,26 @@
#include "exceptions.h"
#include "RedirectionOutput.h"
struct hostfxr_initialize_parameters
{
size_t size;
PCWSTR host_path;
PCWSTR dotnet_root;
};
#define DOTNETCORE_STARTUP_HOOK L"STARTUP_HOOKS"
#define DOTNETCORE_USE_ENTRYPOINT_FILTER L"USE_ENTRYPOINT_FILTER"
#define DOTNETCORE_STACK_SIZE L"DEFAULT_STACK_SIZE"
#define ASPNETCORE_STARTUP_ASSEMBLY L"Microsoft.AspNetCore.Server.IIS"
typedef INT(*hostfxr_get_native_search_directories_fn) (INT argc, CONST PCWSTR* argv, PWSTR buffer, DWORD buffer_size, DWORD* required_buffer_size);
typedef INT(*hostfxr_main_fn) (DWORD argc, CONST PCWSTR argv[]);
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_run_app_fn)(void* host_context_handle);
typedef int(*hostfxr_close_fn)(void* hostfxr_context_handle);
struct ErrorContext
{
@ -49,7 +65,8 @@ public:
corehost_set_error_writer_fn corehost_set_error_writer_fn) noexcept
: m_hostfxr_main_fn(hostfxr_main_fn),
m_hostfxr_get_native_search_directories_fn(hostfxr_get_native_search_directories_fn),
m_corehost_set_error_writer_fn(corehost_set_error_writer_fn)
m_corehost_set_error_writer_fn(corehost_set_error_writer_fn),
m_host_context_handle(nullptr)
{
}
@ -66,10 +83,18 @@ public:
int GetNativeSearchDirectories(INT argc, CONST PCWSTR* argv, PWSTR buffer, DWORD buffer_size, DWORD* required_buffer_size) const noexcept;
HostFxrErrorRedirector RedirectOutput(RedirectionOutput* writer) const noexcept;
int SetRuntimePropertyValue(PCWSTR name, PCWSTR value) const noexcept;
int InitializeForApp(int argc, PCWSTR* argv, const std::wstring& m_dotnetExeKnownLocation) const noexcept;
void Close() const noexcept;
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;
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_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;
void* m_host_context_handle;
};

View File

@ -89,6 +89,9 @@
#define SUCCEEDED_LOG(hr) SUCCEEDED(LOG_IF_FAILED(hr))
#define FAILED_LOG(hr) FAILED(LOG_IF_FAILED(hr))
#define RETURN_INT_IF_NOT_ZERO(val) do { if ((val) != 0) { return val; }} while (0, 0)
#define RETURN_IF_NOT_ZERO(val) do { if ((val) != 0) { return; }} while (0, 0)
inline thread_local IHttpTraceContext* g_traceContext;
__declspec(noinline) inline VOID TraceHRESULT(LOCATION_ARGUMENTS HRESULT hr)

View File

@ -55,7 +55,7 @@ IN_PROCESS_APPLICATION::StopInternal(bool fServerInitiated)
VOID
IN_PROCESS_APPLICATION::StopClr()
{
// This has the state lock around it.
// This has the state lock around it.
LOG_INFO(L"Stopping CLR");
if (!m_blockManagedCallbacks)
@ -241,25 +241,19 @@ IN_PROCESS_APPLICATION::ExecuteApplication()
LOG_INFOF(L"Setting current directory to %s", this->QueryApplicationPhysicalPath().c_str());
}
if (m_pConfig->QueryCallStartupHook())
auto startupReturnCode = context->m_hostFxr.InitializeForApp(context->m_argc, context->m_argv.get(), m_dotnetExeKnownLocation);
if (startupReturnCode != 0)
{
// Used to display developer exception page when there is an exception in main.
auto currentStartupHookEnv = Environment::GetEnvironmentVariableValue(DOTNETCORE_STARTUP_HOOK);
if (currentStartupHookEnv.has_value())
{
currentStartupHookEnv = currentStartupHookEnv.value() + L";" + ASPNETCORE_STARTUP_ASSEMBLY;
LOG_LAST_ERROR_IF(!SetEnvironmentVariable(DOTNETCORE_STARTUP_HOOK, currentStartupHookEnv.value().c_str()));
}
else
{
LOG_LAST_ERROR_IF(!SetEnvironmentVariable(DOTNETCORE_STARTUP_HOOK, ASPNETCORE_STARTUP_ASSEMBLY));
}
throw InvalidOperationException(format(L"Error occured when initializing inprocess application, Return code: 0x%x", startupReturnCode));
}
// Used to make .NET Runtime always log to event log when there is an unhandled exception.
LOG_LAST_ERROR_IF(!SetEnvironmentVariable(L"COMPlus_UseEntryPointFilter", L"1"));
LOG_LAST_ERROR_IF(!SetEnvironmentVariable(L"COMPlus_DefaultStackSize", m_pConfig->QueryStackSize().c_str()));
if (m_pConfig->QueryCallStartupHook())
{
RETURN_IF_NOT_ZERO(context->m_hostFxr.SetRuntimePropertyValue(DOTNETCORE_STARTUP_HOOK, ASPNETCORE_STARTUP_ASSEMBLY));
}
RETURN_IF_NOT_ZERO(context->m_hostFxr.SetRuntimePropertyValue(DOTNETCORE_USE_ENTRYPOINT_FILTER, L"1"));
RETURN_IF_NOT_ZERO(context->m_hostFxr.SetRuntimePropertyValue(DOTNETCORE_STACK_SIZE, m_pConfig->QueryStackSize().c_str()));
bool clrThreadExited;
{
@ -434,6 +428,7 @@ IN_PROCESS_APPLICATION::ExecuteClr(const std::shared_ptr<ExecuteClrContext>& con
LOG_INFOF(L"Managed application exited with code %d", exitCode);
context->m_exitCode = exitCode;
context->m_hostFxr.Close();
}
__except(GetExceptionCode() != 0)
{

View File

@ -15,8 +15,6 @@ typedef BOOL(WINAPI * PFN_SHUTDOWN_HANDLER) (void* pvShutdownHandlerContext);
typedef REQUEST_NOTIFICATION_STATUS(WINAPI * PFN_ASYNC_COMPLETION_HANDLER)(void *pvManagedHttpContext, HRESULT hrCompletionStatus, DWORD cbCompletion);
typedef void(WINAPI * PFN_REQUESTS_DRAINED_HANDLER) (void* pvShutdownHandlerContext);
#define DOTNETCORE_STARTUP_HOOK L"DOTNET_STARTUP_HOOKS"
#define ASPNETCORE_STARTUP_ASSEMBLY L"Microsoft.AspNetCore.Server.IIS"
class IN_PROCESS_APPLICATION : public InProcessApplicationBase
{
public: