From dba8f2e10e6383bb6f0b9e34019509b11a585e31 Mon Sep 17 00:00:00 2001 From: Justin Anderson Date: Wed, 17 May 2023 11:56:50 -0700 Subject: [PATCH 1/7] Allow using active host context in hostfxr_get_runtime_delegate --- .../NativeHosting/HostContext.cs | 26 ++++++ src/native/corehost/fxr/fx_muxer.cpp | 80 +++++++++++++------ src/native/corehost/fxr/fx_muxer.h | 3 + src/native/corehost/fxr/hostfxr.cpp | 17 ++-- .../test/nativehost/host_context_test.cpp | 38 +++++++++ .../test/nativehost/host_context_test.h | 4 + .../corehost/test/nativehost/nativehost.cpp | 4 + 7 files changed, 144 insertions(+), 28 deletions(-) diff --git a/src/installer/tests/HostActivation.Tests/NativeHosting/HostContext.cs b/src/installer/tests/HostActivation.Tests/NativeHosting/HostContext.cs index 4e80ca7f2b2b7f..7ecb67a3c20d14 100644 --- a/src/installer/tests/HostActivation.Tests/NativeHosting/HostContext.cs +++ b/src/installer/tests/HostActivation.Tests/NativeHosting/HostContext.cs @@ -21,6 +21,7 @@ public class Scenario public const string Mixed = "mixed"; public const string NonContextMixedAppHost = "non_context_mixed_apphost"; public const string NonContextMixedDotnet = "non_context_mixed_dotnet"; + public const string GetRuntimeDelegate = "get_runtime_delegate"; } public class CheckProperties @@ -237,6 +238,31 @@ public void GetDelegate_Multiple(string checkProperties) propertyValidation.ValidateSecondaryContext(result, SharedTestState.SecondaryConfigPropertyName, SharedTestState.SecondaryConfigPropertyValue); } + [Fact] + public void GetDelegate_Active() + { + string newPropertyName = "HOST_TEST_PROPERTY"; + string[] args = + { + HostContextArg, + Scenario.GetRuntimeDelegate, + CheckProperties.None, + sharedState.HostFxrPath, + sharedState.RuntimeConfigPath, + SharedTestState.ConfigPropertyName, + newPropertyName + }; + CommandResult result = sharedState.CreateNativeHostCommand(args, sharedState.DotNetRoot) + .Execute(); + + result.Should().Pass() + .And.InitializeContextForConfig(sharedState.RuntimeConfigPath) + .And.CreateDelegateMock_COM(); + + CheckPropertiesValidation propertyValidation = new CheckPropertiesValidation(CheckProperties.None, LogPrefix.Config, SharedTestState.ConfigPropertyName, SharedTestState.ConfigPropertyValue); + propertyValidation.ValidateActiveContext(result, newPropertyName); + } + [Theory] [InlineData(Scenario.Mixed, CheckProperties.None)] [InlineData(Scenario.Mixed, CheckProperties.Get)] diff --git a/src/native/corehost/fxr/fx_muxer.cpp b/src/native/corehost/fxr/fx_muxer.cpp index 20df9462abb869..9bcd2b4da3061c 100644 --- a/src/native/corehost/fxr/fx_muxer.cpp +++ b/src/native/corehost/fxr/fx_muxer.cpp @@ -857,6 +857,36 @@ namespace g_context_initializing_cv.notify_all(); return rc; } + + int get_runtime_delegate_validate(const host_context_t *context, coreclr_delegate_type type) + { + switch (type) + { + case coreclr_delegate_type::com_activation: + case coreclr_delegate_type::load_in_memory_assembly: + case coreclr_delegate_type::winrt_activation: + case coreclr_delegate_type::com_register: + case coreclr_delegate_type::com_unregister: + if (context->is_app) + return StatusCode::HostApiUnsupportedScenario; + break; + default: + // Always allowed + break; + } + + // last_known_delegate_type was added in 5.0, so old versions won't set it and it will be zero. + // But when get_runtime_delegate was originally implemented in 3.0, + // it supported up to load_assembly_and_get_function_pointer so we check that first. + if (type > coreclr_delegate_type::load_assembly_and_get_function_pointer + && (size_t)type > context->hostpolicy_context_contract.last_known_delegate_type) + { + trace::error(_X("The requested delegate type is not available in the target framework.")); + return StatusCode::HostApiUnsupportedVersion; + } + + return StatusCode::Success; + } } int fx_muxer_t::run_app(host_context_t *context) @@ -884,29 +914,10 @@ int fx_muxer_t::run_app(host_context_t *context) int fx_muxer_t::get_runtime_delegate(host_context_t *context, coreclr_delegate_type type, void **delegate) { - switch (type) - { - case coreclr_delegate_type::com_activation: - case coreclr_delegate_type::load_in_memory_assembly: - case coreclr_delegate_type::winrt_activation: - case coreclr_delegate_type::com_register: - case coreclr_delegate_type::com_unregister: - if (context->is_app) - return StatusCode::HostApiUnsupportedScenario; - break; - default: - // Always allowed - break; - } - - // last_known_delegate_type was added in 5.0, so old versions won't set it and it will be zero. - // But when get_runtime_delegate was originally implemented in 3.0, - // it supported up to load_assembly_and_get_function_pointer so we check that first. - if (type > coreclr_delegate_type::load_assembly_and_get_function_pointer - && (size_t)type > context->hostpolicy_context_contract.last_known_delegate_type) + int rc = get_runtime_delegate_validate(context, type); + if (!STATUS_CODE_SUCCEEDED(rc)) { - trace::error(_X("The requested delegate type is not available in the target framework.")); - return StatusCode::HostApiUnsupportedVersion; + return rc; } const corehost_context_contract &contract = context->hostpolicy_context_contract; @@ -915,7 +926,7 @@ int fx_muxer_t::get_runtime_delegate(host_context_t *context, coreclr_delegate_t if (context->type != host_context_type::secondary) { - int rc = load_runtime(context); + rc = load_runtime(context); if (rc != StatusCode::Success) return rc; } @@ -924,6 +935,29 @@ int fx_muxer_t::get_runtime_delegate(host_context_t *context, coreclr_delegate_t } } +int fx_muxer_t::get_runtime_delegate_active(coreclr_delegate_type type, void **delegate) +{ + const host_context_t *context = get_active_host_context(); + if (context == nullptr) + { + trace::error(_X("Hosting components context has not been initialized. Cannot get runtime delegate.")); + return StatusCode::HostInvalidState; + } + + int rc = get_runtime_delegate_validate(context, type); + if (!STATUS_CODE_SUCCEEDED(rc)) + { + return rc; + } + + const corehost_context_contract &contract = context->hostpolicy_context_contract; + { + propagate_error_writer_t propagate_error_writer_to_corehost(context->hostpolicy_contract.set_error_writer); + + return contract.get_runtime_delegate(type, delegate); + } +} + const host_context_t* fx_muxer_t::get_active_host_context() { std::lock_guard lock{ g_context_lock }; diff --git a/src/native/corehost/fxr/fx_muxer.h b/src/native/corehost/fxr/fx_muxer.h index b3a0e0004700a8..84efbdb984f140 100644 --- a/src/native/corehost/fxr/fx_muxer.h +++ b/src/native/corehost/fxr/fx_muxer.h @@ -35,6 +35,9 @@ class fx_muxer_t host_context_t *context, coreclr_delegate_type delegate_type, void** delegate); + static int get_runtime_delegate_active( + coreclr_delegate_type delegate_type, + void** delegate); static const host_context_t* get_active_host_context(); static int close_host_context(host_context_t *context); private: diff --git a/src/native/corehost/fxr/hostfxr.cpp b/src/native/corehost/fxr/hostfxr.cpp index 0df1b24cda77f4..2c6779b7555b9b 100644 --- a/src/native/corehost/fxr/hostfxr.cpp +++ b/src/native/corehost/fxr/hostfxr.cpp @@ -688,15 +688,22 @@ SHARED_API int32_t HOSTFXR_CALLTYPE hostfxr_get_runtime_delegate( *delegate = nullptr; - host_context_t *context = host_context_t::from_handle(host_context_handle); - if (context == nullptr) - return StatusCode::InvalidArgFailure; - coreclr_delegate_type delegate_type = hostfxr_delegate_to_coreclr_delegate(type); if (delegate_type == coreclr_delegate_type::invalid) return StatusCode::InvalidArgFailure; - return fx_muxer_t::get_runtime_delegate(context, delegate_type, delegate); + if (host_context_handle == nullptr) + { + return fx_muxer_t::get_runtime_delegate_active(delegate_type, delegate); + } + else + { + host_context_t *context = host_context_t::from_handle(host_context_handle); + if (context == nullptr) + return StatusCode::InvalidArgFailure; + + return fx_muxer_t::get_runtime_delegate(context, delegate_type, delegate); + } } SHARED_API int32_t HOSTFXR_CALLTYPE hostfxr_get_runtime_property_value( diff --git a/src/native/corehost/test/nativehost/host_context_test.cpp b/src/native/corehost/test/nativehost/host_context_test.cpp index 24b649515d685a..6005cb883a5b2c 100644 --- a/src/native/corehost/test/nativehost/host_context_test.cpp +++ b/src/native/corehost/test/nativehost/host_context_test.cpp @@ -688,6 +688,34 @@ namespace return success && rcClose == StatusCode::Success; } + + bool get_runtime_delegate_test( + const hostfxr_exports &hostfxr, + const pal::char_t *config_path, + hostfxr_delegate_type delegate_type1, + hostfxr_delegate_type delegate_type2, + const pal::char_t *log_prefix, + pal::stringstream_t &test_output) + { + hostfxr_handle handle; + if (!init_for_config(hostfxr, config_path, &handle, log_prefix, test_output)) + return false; + + void *delegate1; + bool success = get_runtime_delegate(hostfxr, handle, delegate_type1, &delegate1, log_prefix, test_output); + + // Testing that using the active host context works for get_runtime_delegate + // by passing nullptr for handle parameter. The runtime must be loaded for this to succeed; + // the first call to get_runtime_delegate with a defined handle ensures that it is loaded. + void *delegate2; + success &= get_runtime_delegate(hostfxr, nullptr, delegate_type2, &delegate2, log_prefix, test_output); + + int rcClose = hostfxr.close(handle); + if (rcClose != StatusCode::Success) + test_output << log_prefix << _X("hostfxr_close failed: ") << std::hex << std::showbase << rcClose << std::endl; + + return success && rcClose == StatusCode::Success; + } } host_context_test::check_properties host_context_test::check_properties_from_string(const pal::char_t *str) @@ -1000,3 +1028,13 @@ bool host_context_test::app_get_function_pointer( return app_get_function_pointer_test(hostfxr, argc, argv, config_log_prefix, test_output); } + +bool host_context_test::get_runtime_delegate( + const pal::string_t &hostfxr_path, + const pal::char_t *config_path, + pal::stringstream_t &test_output) +{ + hostfxr_exports hostfxr{ hostfxr_path }; + + return get_runtime_delegate_test(hostfxr, config_path, first_delegate_type, secondary_delegate_type, config_log_prefix, test_output); +} diff --git a/src/native/corehost/test/nativehost/host_context_test.h b/src/native/corehost/test/nativehost/host_context_test.h index 4d6b5d0cf74788..7d13f4a77a26aa 100644 --- a/src/native/corehost/test/nativehost/host_context_test.h +++ b/src/native/corehost/test/nativehost/host_context_test.h @@ -103,4 +103,8 @@ namespace host_context_test int argc, const pal::char_t *argv[], pal::stringstream_t &test_output); + bool get_runtime_delegate( + const pal::string_t &hostfxr_path, + const pal::char_t *config_path, + pal::stringstream_t &test_output); } diff --git a/src/native/corehost/test/nativehost/nativehost.cpp b/src/native/corehost/test/nativehost/nativehost.cpp index b53db3a65eaa93..8a9aedd5d6719e 100644 --- a/src/native/corehost/test/nativehost/nativehost.cpp +++ b/src/native/corehost/test/nativehost/nativehost.cpp @@ -207,6 +207,10 @@ int main(const int argc, const pal::char_t *argv[]) bool launch_as_if_dotnet = pal::strcmp(scenario, _X("non_context_mixed_dotnet")) == 0; success = host_context_test::non_context_mixed(check_properties, hostfxr_path, app_or_config_path, config_path, remaining_argc, remaining_argv, launch_as_if_dotnet, test_output); } + else if (pal::strcmp(scenario, _X("get_runtime_delegate")) == 0) + { + success = host_context_test::get_runtime_delegate(hostfxr_path, app_or_config_path, test_output); + } else { std::cerr << "Invalid scenario" << std::endl; From be62fa51bd5f29dd71ed199ca63a3f9ea48051b3 Mon Sep 17 00:00:00 2001 From: Justin Anderson Date: Fri, 19 May 2023 09:18:12 -0700 Subject: [PATCH 2/7] Rename test methods and scenario --- .../tests/HostActivation.Tests/NativeHosting/HostContext.cs | 6 +++--- src/native/corehost/test/nativehost/host_context_test.cpp | 6 +++--- src/native/corehost/test/nativehost/host_context_test.h | 2 +- src/native/corehost/test/nativehost/nativehost.cpp | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/installer/tests/HostActivation.Tests/NativeHosting/HostContext.cs b/src/installer/tests/HostActivation.Tests/NativeHosting/HostContext.cs index 7ecb67a3c20d14..2ed3655ab5d767 100644 --- a/src/installer/tests/HostActivation.Tests/NativeHosting/HostContext.cs +++ b/src/installer/tests/HostActivation.Tests/NativeHosting/HostContext.cs @@ -21,7 +21,7 @@ public class Scenario public const string Mixed = "mixed"; public const string NonContextMixedAppHost = "non_context_mixed_apphost"; public const string NonContextMixedDotnet = "non_context_mixed_dotnet"; - public const string GetRuntimeDelegate = "get_runtime_delegate"; + public const string GetRuntimeDelegateForActiveContext = "get_runtime_delegate_for_active_context"; } public class CheckProperties @@ -239,13 +239,13 @@ public void GetDelegate_Multiple(string checkProperties) } [Fact] - public void GetDelegate_Active() + public void GetDelegate_ActiveContext() { string newPropertyName = "HOST_TEST_PROPERTY"; string[] args = { HostContextArg, - Scenario.GetRuntimeDelegate, + Scenario.GetRuntimeDelegateForActiveContext, CheckProperties.None, sharedState.HostFxrPath, sharedState.RuntimeConfigPath, diff --git a/src/native/corehost/test/nativehost/host_context_test.cpp b/src/native/corehost/test/nativehost/host_context_test.cpp index 6005cb883a5b2c..a4e8927784251e 100644 --- a/src/native/corehost/test/nativehost/host_context_test.cpp +++ b/src/native/corehost/test/nativehost/host_context_test.cpp @@ -689,7 +689,7 @@ namespace return success && rcClose == StatusCode::Success; } - bool get_runtime_delegate_test( + bool get_runtime_delegate_for_active_context_test( const hostfxr_exports &hostfxr, const pal::char_t *config_path, hostfxr_delegate_type delegate_type1, @@ -1029,12 +1029,12 @@ bool host_context_test::app_get_function_pointer( return app_get_function_pointer_test(hostfxr, argc, argv, config_log_prefix, test_output); } -bool host_context_test::get_runtime_delegate( +bool host_context_test::get_runtime_delegate_for_active_context( const pal::string_t &hostfxr_path, const pal::char_t *config_path, pal::stringstream_t &test_output) { hostfxr_exports hostfxr{ hostfxr_path }; - return get_runtime_delegate_test(hostfxr, config_path, first_delegate_type, secondary_delegate_type, config_log_prefix, test_output); + return get_runtime_delegate_for_active_context_test(hostfxr, config_path, first_delegate_type, secondary_delegate_type, config_log_prefix, test_output); } diff --git a/src/native/corehost/test/nativehost/host_context_test.h b/src/native/corehost/test/nativehost/host_context_test.h index 7d13f4a77a26aa..44d9fb9e0343d7 100644 --- a/src/native/corehost/test/nativehost/host_context_test.h +++ b/src/native/corehost/test/nativehost/host_context_test.h @@ -103,7 +103,7 @@ namespace host_context_test int argc, const pal::char_t *argv[], pal::stringstream_t &test_output); - bool get_runtime_delegate( + bool get_runtime_delegate_for_active_context( const pal::string_t &hostfxr_path, const pal::char_t *config_path, pal::stringstream_t &test_output); diff --git a/src/native/corehost/test/nativehost/nativehost.cpp b/src/native/corehost/test/nativehost/nativehost.cpp index 8a9aedd5d6719e..214e2b9af9122c 100644 --- a/src/native/corehost/test/nativehost/nativehost.cpp +++ b/src/native/corehost/test/nativehost/nativehost.cpp @@ -207,9 +207,9 @@ int main(const int argc, const pal::char_t *argv[]) bool launch_as_if_dotnet = pal::strcmp(scenario, _X("non_context_mixed_dotnet")) == 0; success = host_context_test::non_context_mixed(check_properties, hostfxr_path, app_or_config_path, config_path, remaining_argc, remaining_argv, launch_as_if_dotnet, test_output); } - else if (pal::strcmp(scenario, _X("get_runtime_delegate")) == 0) + else if (pal::strcmp(scenario, _X("get_runtime_delegate_for_active_context")) == 0) { - success = host_context_test::get_runtime_delegate(hostfxr_path, app_or_config_path, test_output); + success = host_context_test::get_runtime_delegate_for_active_context(hostfxr_path, app_or_config_path, test_output); } else { From 927e49f316f1fd6246e60bc70af7317ac6a039b5 Mon Sep 17 00:00:00 2001 From: Justin Anderson Date: Fri, 19 May 2023 09:19:39 -0700 Subject: [PATCH 3/7] Validate secondary delegate --- .../tests/HostActivation.Tests/NativeHosting/HostContext.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/installer/tests/HostActivation.Tests/NativeHosting/HostContext.cs b/src/installer/tests/HostActivation.Tests/NativeHosting/HostContext.cs index 2ed3655ab5d767..a3db96a9f733ad 100644 --- a/src/installer/tests/HostActivation.Tests/NativeHosting/HostContext.cs +++ b/src/installer/tests/HostActivation.Tests/NativeHosting/HostContext.cs @@ -257,7 +257,8 @@ public void GetDelegate_ActiveContext() result.Should().Pass() .And.InitializeContextForConfig(sharedState.RuntimeConfigPath) - .And.CreateDelegateMock_COM(); + .And.CreateDelegateMock_COM() + .And.CreateDelegateMock_InMemoryAssembly(); CheckPropertiesValidation propertyValidation = new CheckPropertiesValidation(CheckProperties.None, LogPrefix.Config, SharedTestState.ConfigPropertyName, SharedTestState.ConfigPropertyValue); propertyValidation.ValidateActiveContext(result, newPropertyName); From 157161bd277ed70e734151e698b56bf9f2405579 Mon Sep 17 00:00:00 2001 From: Justin Anderson Date: Fri, 19 May 2023 11:44:42 -0700 Subject: [PATCH 4/7] Recombine get_runtime_delegate variants --- src/native/corehost/fxr/fx_muxer.cpp | 90 ++++++++++------------------ src/native/corehost/fxr/fx_muxer.h | 3 - src/native/corehost/fxr/hostfxr.cpp | 2 +- 3 files changed, 33 insertions(+), 62 deletions(-) diff --git a/src/native/corehost/fxr/fx_muxer.cpp b/src/native/corehost/fxr/fx_muxer.cpp index 9bcd2b4da3061c..c12c0fda45fea2 100644 --- a/src/native/corehost/fxr/fx_muxer.cpp +++ b/src/native/corehost/fxr/fx_muxer.cpp @@ -857,36 +857,6 @@ namespace g_context_initializing_cv.notify_all(); return rc; } - - int get_runtime_delegate_validate(const host_context_t *context, coreclr_delegate_type type) - { - switch (type) - { - case coreclr_delegate_type::com_activation: - case coreclr_delegate_type::load_in_memory_assembly: - case coreclr_delegate_type::winrt_activation: - case coreclr_delegate_type::com_register: - case coreclr_delegate_type::com_unregister: - if (context->is_app) - return StatusCode::HostApiUnsupportedScenario; - break; - default: - // Always allowed - break; - } - - // last_known_delegate_type was added in 5.0, so old versions won't set it and it will be zero. - // But when get_runtime_delegate was originally implemented in 3.0, - // it supported up to load_assembly_and_get_function_pointer so we check that first. - if (type > coreclr_delegate_type::load_assembly_and_get_function_pointer - && (size_t)type > context->hostpolicy_context_contract.last_known_delegate_type) - { - trace::error(_X("The requested delegate type is not available in the target framework.")); - return StatusCode::HostApiUnsupportedVersion; - } - - return StatusCode::Success; - } } int fx_muxer_t::run_app(host_context_t *context) @@ -914,45 +884,49 @@ int fx_muxer_t::run_app(host_context_t *context) int fx_muxer_t::get_runtime_delegate(host_context_t *context, coreclr_delegate_type type, void **delegate) { - int rc = get_runtime_delegate_validate(context, type); - if (!STATUS_CODE_SUCCEEDED(rc)) - { - return rc; - } + const host_context_t* context_local = context == nullptr ? get_active_host_context() : context; - const corehost_context_contract &contract = context->hostpolicy_context_contract; + if (context_local == nullptr) { - propagate_error_writer_t propagate_error_writer_to_corehost(context->hostpolicy_contract.set_error_writer); - - if (context->type != host_context_type::secondary) - { - rc = load_runtime(context); - if (rc != StatusCode::Success) - return rc; - } - - return contract.get_runtime_delegate(type, delegate); + trace::error(_X("Hosting components context has not been initialized. Cannot get runtime delegate.")); + return StatusCode::HostInvalidState; } -} -int fx_muxer_t::get_runtime_delegate_active(coreclr_delegate_type type, void **delegate) -{ - const host_context_t *context = get_active_host_context(); - if (context == nullptr) + switch (type) { - trace::error(_X("Hosting components context has not been initialized. Cannot get runtime delegate.")); - return StatusCode::HostInvalidState; + case coreclr_delegate_type::com_activation: + case coreclr_delegate_type::load_in_memory_assembly: + case coreclr_delegate_type::winrt_activation: + case coreclr_delegate_type::com_register: + case coreclr_delegate_type::com_unregister: + if (context_local->is_app) + return StatusCode::HostApiUnsupportedScenario; + break; + default: + // Always allowed + break; } - int rc = get_runtime_delegate_validate(context, type); - if (!STATUS_CODE_SUCCEEDED(rc)) + // last_known_delegate_type was added in 5.0, so old versions won't set it and it will be zero. + // But when get_runtime_delegate was originally implemented in 3.0, + // it supported up to load_assembly_and_get_function_pointer so we check that first. + if (type > coreclr_delegate_type::load_assembly_and_get_function_pointer + && (size_t)type > context_local->hostpolicy_context_contract.last_known_delegate_type) { - return rc; + trace::error(_X("The requested delegate type is not available in the target framework.")); + return StatusCode::HostApiUnsupportedVersion; } - const corehost_context_contract &contract = context->hostpolicy_context_contract; + const corehost_context_contract &contract = context_local->hostpolicy_context_contract; { - propagate_error_writer_t propagate_error_writer_to_corehost(context->hostpolicy_contract.set_error_writer); + propagate_error_writer_t propagate_error_writer_to_corehost(context_local->hostpolicy_contract.set_error_writer); + + if (context_local->type != host_context_type::secondary) + { + int rc = load_runtime(context); + if (rc != StatusCode::Success) + return rc; + } return contract.get_runtime_delegate(type, delegate); } diff --git a/src/native/corehost/fxr/fx_muxer.h b/src/native/corehost/fxr/fx_muxer.h index 84efbdb984f140..b3a0e0004700a8 100644 --- a/src/native/corehost/fxr/fx_muxer.h +++ b/src/native/corehost/fxr/fx_muxer.h @@ -35,9 +35,6 @@ class fx_muxer_t host_context_t *context, coreclr_delegate_type delegate_type, void** delegate); - static int get_runtime_delegate_active( - coreclr_delegate_type delegate_type, - void** delegate); static const host_context_t* get_active_host_context(); static int close_host_context(host_context_t *context); private: diff --git a/src/native/corehost/fxr/hostfxr.cpp b/src/native/corehost/fxr/hostfxr.cpp index 2c6779b7555b9b..a0e796b09e0272 100644 --- a/src/native/corehost/fxr/hostfxr.cpp +++ b/src/native/corehost/fxr/hostfxr.cpp @@ -694,7 +694,7 @@ SHARED_API int32_t HOSTFXR_CALLTYPE hostfxr_get_runtime_delegate( if (host_context_handle == nullptr) { - return fx_muxer_t::get_runtime_delegate_active(delegate_type, delegate); + return fx_muxer_t::get_runtime_delegate(nullptr, delegate_type, delegate); } else { From c5c2ae068226551ec4cabb08f145f6109f1a734a Mon Sep 17 00:00:00 2001 From: Justin Anderson Date: Fri, 19 May 2023 11:56:47 -0700 Subject: [PATCH 5/7] Validate failure before runtime is loaded --- .../test/nativehost/host_context_test.cpp | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/native/corehost/test/nativehost/host_context_test.cpp b/src/native/corehost/test/nativehost/host_context_test.cpp index a4e8927784251e..b7c8c983d3a471 100644 --- a/src/native/corehost/test/nativehost/host_context_test.cpp +++ b/src/native/corehost/test/nativehost/host_context_test.cpp @@ -701,12 +701,27 @@ namespace if (!init_for_config(hostfxr, config_path, &handle, log_prefix, test_output)) return false; - void *delegate1; - bool success = get_runtime_delegate(hostfxr, handle, delegate_type1, &delegate1, log_prefix, test_output); + void *delegate1 = nullptr; + // Check that using get_runtime_delegate with the active host context will fail + // due to the runtime not being loaded yet. + bool success = get_runtime_delegate(hostfxr, nullptr, delegate_type1, &delegate1, log_prefix, test_output); + if (success) + { + test_output << log_prefix << _X("get_runtime_delegate with active context succeeded unexpectedly.") << std::endl; + return false; + } + if (nullptr != delegate1) + { + test_output << log_prefix << _X("Unexpectedly got a runtime delegate when get_runtime_delegate failed.") << std::endl; + return false; + } + + // Successfully get first delegate with a defined handle. + success = get_runtime_delegate(hostfxr, handle, delegate_type1, &delegate1, log_prefix, test_output); // Testing that using the active host context works for get_runtime_delegate // by passing nullptr for handle parameter. The runtime must be loaded for this to succeed; - // the first call to get_runtime_delegate with a defined handle ensures that it is loaded. + // the first successful call to get_runtime_delegate with a defined handle ensures that it is loaded. void *delegate2; success &= get_runtime_delegate(hostfxr, nullptr, delegate_type2, &delegate2, log_prefix, test_output); From 9efedb894d954c63316ea42fe526c31db9591e7e Mon Sep 17 00:00:00 2001 From: Justin Anderson Date: Fri, 19 May 2023 12:11:02 -0700 Subject: [PATCH 6/7] Make load_runtime separate from get_runtime_delegate --- src/native/corehost/fxr/fx_muxer.cpp | 62 ++++++++++------------------ src/native/corehost/fxr/fx_muxer.h | 3 +- src/native/corehost/fxr/hostfxr.cpp | 28 +++++++++++-- 3 files changed, 48 insertions(+), 45 deletions(-) diff --git a/src/native/corehost/fxr/fx_muxer.cpp b/src/native/corehost/fxr/fx_muxer.cpp index c12c0fda45fea2..efabe7446d52bd 100644 --- a/src/native/corehost/fxr/fx_muxer.cpp +++ b/src/native/corehost/fxr/fx_muxer.cpp @@ -833,30 +833,27 @@ int fx_muxer_t::initialize_for_runtime_config( return rc; } -namespace +int fx_muxer_t::load_runtime(host_context_t *context) { - int load_runtime(host_context_t *context) - { - assert(context->type == host_context_type::initialized || context->type == host_context_type::active); - if (context->type == host_context_type::active) - return StatusCode::Success; + assert(context->type == host_context_type::initialized || context->type == host_context_type::active); + if (context->type == host_context_type::active) + return StatusCode::Success; - const corehost_context_contract &contract = context->hostpolicy_context_contract; - int rc = contract.load_runtime(); + const corehost_context_contract &contract = context->hostpolicy_context_contract; + int rc = contract.load_runtime(); - // Mark the context as active or invalid - context->type = rc == StatusCode::Success ? host_context_type::active : host_context_type::invalid; + // Mark the context as active or invalid + context->type = rc == StatusCode::Success ? host_context_type::active : host_context_type::invalid; - { - std::lock_guard lock{ g_context_lock }; - assert(g_active_host_context == nullptr); - g_active_host_context.reset(context); - g_context_initializing.store(false); - } - - g_context_initializing_cv.notify_all(); - return rc; + { + std::lock_guard lock{ g_context_lock }; + assert(g_active_host_context == nullptr); + g_active_host_context.reset(context); + g_context_initializing.store(false); } + + g_context_initializing_cv.notify_all(); + return rc; } int fx_muxer_t::run_app(host_context_t *context) @@ -874,7 +871,7 @@ int fx_muxer_t::run_app(host_context_t *context) { propagate_error_writer_t propagate_error_writer_to_corehost(context->hostpolicy_contract.set_error_writer); - int rc = load_runtime(context); + int rc = fx_muxer_t::load_runtime(context); if (rc != StatusCode::Success) return rc; @@ -882,16 +879,8 @@ int fx_muxer_t::run_app(host_context_t *context) } } -int fx_muxer_t::get_runtime_delegate(host_context_t *context, coreclr_delegate_type type, void **delegate) +int fx_muxer_t::get_runtime_delegate(const host_context_t *context, coreclr_delegate_type type, void **delegate) { - const host_context_t* context_local = context == nullptr ? get_active_host_context() : context; - - if (context_local == nullptr) - { - trace::error(_X("Hosting components context has not been initialized. Cannot get runtime delegate.")); - return StatusCode::HostInvalidState; - } - switch (type) { case coreclr_delegate_type::com_activation: @@ -899,7 +888,7 @@ int fx_muxer_t::get_runtime_delegate(host_context_t *context, coreclr_delegate_t case coreclr_delegate_type::winrt_activation: case coreclr_delegate_type::com_register: case coreclr_delegate_type::com_unregister: - if (context_local->is_app) + if (context->is_app) return StatusCode::HostApiUnsupportedScenario; break; default: @@ -911,22 +900,15 @@ int fx_muxer_t::get_runtime_delegate(host_context_t *context, coreclr_delegate_t // But when get_runtime_delegate was originally implemented in 3.0, // it supported up to load_assembly_and_get_function_pointer so we check that first. if (type > coreclr_delegate_type::load_assembly_and_get_function_pointer - && (size_t)type > context_local->hostpolicy_context_contract.last_known_delegate_type) + && (size_t)type > context->hostpolicy_context_contract.last_known_delegate_type) { trace::error(_X("The requested delegate type is not available in the target framework.")); return StatusCode::HostApiUnsupportedVersion; } - const corehost_context_contract &contract = context_local->hostpolicy_context_contract; + const corehost_context_contract &contract = context->hostpolicy_context_contract; { - propagate_error_writer_t propagate_error_writer_to_corehost(context_local->hostpolicy_contract.set_error_writer); - - if (context_local->type != host_context_type::secondary) - { - int rc = load_runtime(context); - if (rc != StatusCode::Success) - return rc; - } + propagate_error_writer_t propagate_error_writer_to_corehost(context->hostpolicy_contract.set_error_writer); return contract.get_runtime_delegate(type, delegate); } diff --git a/src/native/corehost/fxr/fx_muxer.h b/src/native/corehost/fxr/fx_muxer.h index b3a0e0004700a8..6a9daeb5fb5cc4 100644 --- a/src/native/corehost/fxr/fx_muxer.h +++ b/src/native/corehost/fxr/fx_muxer.h @@ -32,11 +32,12 @@ class fx_muxer_t hostfxr_handle *host_context_handle); static int run_app(host_context_t *context); static int get_runtime_delegate( - host_context_t *context, + const host_context_t *context, coreclr_delegate_type delegate_type, void** delegate); static const host_context_t* get_active_host_context(); static int close_host_context(host_context_t *context); + static int load_runtime(host_context_t *context); private: static int handle_exec_host_command( const pal::string_t& host_command, diff --git a/src/native/corehost/fxr/hostfxr.cpp b/src/native/corehost/fxr/hostfxr.cpp index a0e796b09e0272..c96de5f9dd33a0 100644 --- a/src/native/corehost/fxr/hostfxr.cpp +++ b/src/native/corehost/fxr/hostfxr.cpp @@ -692,18 +692,38 @@ SHARED_API int32_t HOSTFXR_CALLTYPE hostfxr_get_runtime_delegate( if (delegate_type == coreclr_delegate_type::invalid) return StatusCode::InvalidArgFailure; + const host_context_t *context; + host_context_t *context_from_handle = nullptr; if (host_context_handle == nullptr) { - return fx_muxer_t::get_runtime_delegate(nullptr, delegate_type, delegate); + context = fx_muxer_t::get_active_host_context(); + if (context == nullptr) + { + trace::error(_X("Hosting components context has not been initialized. Cannot get runtime properties.")); + return StatusCode::HostInvalidState; + } } else { - host_context_t *context = host_context_t::from_handle(host_context_handle); - if (context == nullptr) + context_from_handle = host_context_t::from_handle(host_context_handle); + if (context_from_handle == nullptr) return StatusCode::InvalidArgFailure; - return fx_muxer_t::get_runtime_delegate(context, delegate_type, delegate); + context = context_from_handle; } + + int rc = fx_muxer_t::get_runtime_delegate(context, delegate_type, delegate); + if (rc != StatusCode::Success) + return rc; + + if (context_from_handle == nullptr && context_from_handle->type != host_context_type::secondary) + { + rc = fx_muxer_t::load_runtime(context_from_handle); + if (rc != StatusCode::Success) + return rc; + } + + return StatusCode::Success; } SHARED_API int32_t HOSTFXR_CALLTYPE hostfxr_get_runtime_property_value( From 99caa6fa042e27fd4e8f8b998622762c92a88752 Mon Sep 17 00:00:00 2001 From: Justin Anderson Date: Fri, 19 May 2023 12:19:31 -0700 Subject: [PATCH 7/7] Maintain existing ordering of load_runtime and get_runtime_delegate --- src/native/corehost/fxr/hostfxr.cpp | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/native/corehost/fxr/hostfxr.cpp b/src/native/corehost/fxr/hostfxr.cpp index c96de5f9dd33a0..a6710dcf626b2c 100644 --- a/src/native/corehost/fxr/hostfxr.cpp +++ b/src/native/corehost/fxr/hostfxr.cpp @@ -693,7 +693,6 @@ SHARED_API int32_t HOSTFXR_CALLTYPE hostfxr_get_runtime_delegate( return StatusCode::InvalidArgFailure; const host_context_t *context; - host_context_t *context_from_handle = nullptr; if (host_context_handle == nullptr) { context = fx_muxer_t::get_active_host_context(); @@ -705,25 +704,21 @@ SHARED_API int32_t HOSTFXR_CALLTYPE hostfxr_get_runtime_delegate( } else { - context_from_handle = host_context_t::from_handle(host_context_handle); + host_context_t *context_from_handle = host_context_t::from_handle(host_context_handle); if (context_from_handle == nullptr) return StatusCode::InvalidArgFailure; - context = context_from_handle; - } + if (context_from_handle->type != host_context_type::secondary) + { + int rc = fx_muxer_t::load_runtime(context_from_handle); + if (rc != StatusCode::Success) + return rc; + } - int rc = fx_muxer_t::get_runtime_delegate(context, delegate_type, delegate); - if (rc != StatusCode::Success) - return rc; - - if (context_from_handle == nullptr && context_from_handle->type != host_context_type::secondary) - { - rc = fx_muxer_t::load_runtime(context_from_handle); - if (rc != StatusCode::Success) - return rc; + context = context_from_handle; } - return StatusCode::Success; + return fx_muxer_t::get_runtime_delegate(context, delegate_type, delegate); } SHARED_API int32_t HOSTFXR_CALLTYPE hostfxr_get_runtime_property_value(