Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 GetRuntimeDelegateForActiveContext = "get_runtime_delegate_for_active_context";
}

public class CheckProperties
Expand Down Expand Up @@ -237,6 +238,32 @@ public void GetDelegate_Multiple(string checkProperties)
propertyValidation.ValidateSecondaryContext(result, SharedTestState.SecondaryConfigPropertyName, SharedTestState.SecondaryConfigPropertyValue);
}

[Fact]
public void GetDelegate_ActiveContext()
{
string newPropertyName = "HOST_TEST_PROPERTY";
string[] args =
{
HostContextArg,
Scenario.GetRuntimeDelegateForActiveContext,
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()
.And.CreateDelegateMock_InMemoryAssembly();

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)]
Expand Down
46 changes: 18 additions & 28 deletions src/native/corehost/fxr/fx_muxer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

const corehost_context_contract &contract = context->hostpolicy_context_contract;
int rc = contract.load_runtime();
assert(context->type == host_context_type::initialized || context->type == host_context_type::active);
if (context->type == host_context_type::active)
return StatusCode::Success;

// Mark the context as active or invalid
context->type = rc == StatusCode::Success ? host_context_type::active : host_context_type::invalid;
const corehost_context_contract &contract = context->hostpolicy_context_contract;
int rc = contract.load_runtime();

{
std::lock_guard<std::mutex> lock{ g_context_lock };
assert(g_active_host_context == nullptr);
g_active_host_context.reset(context);
g_context_initializing.store(false);
}
// Mark the context as active or invalid
context->type = rc == StatusCode::Success ? host_context_type::active : host_context_type::invalid;

g_context_initializing_cv.notify_all();
return rc;
{
std::lock_guard<std::mutex> 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)
Expand All @@ -874,15 +871,15 @@ 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;

return contract.run_app((int32_t)argc, argv.data());
}
}

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)
{
switch (type)
{
Expand Down Expand Up @@ -913,13 +910,6 @@ int fx_muxer_t::get_runtime_delegate(host_context_t *context, coreclr_delegate_t
{
propagate_error_writer_t propagate_error_writer_to_corehost(context->hostpolicy_contract.set_error_writer);

if (context->type != host_context_type::secondary)
{
int rc = load_runtime(context);
if (rc != StatusCode::Success)
return rc;
}

return contract.get_runtime_delegate(type, delegate);
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/native/corehost/fxr/fx_muxer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
30 changes: 26 additions & 4 deletions src/native/corehost/fxr/hostfxr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -688,14 +688,36 @@ 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;

const host_context_t *context;
if (host_context_handle == nullptr)
{
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_from_handle = host_context_t::from_handle(host_context_handle);
if (context_from_handle == nullptr)
return StatusCode::InvalidArgFailure;

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;
}

context = context_from_handle;
}

return fx_muxer_t::get_runtime_delegate(context, delegate_type, delegate);
}

Expand Down
53 changes: 53 additions & 0 deletions src/native/corehost/test/nativehost/host_context_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,49 @@ namespace

return success && rcClose == StatusCode::Success;
}

bool get_runtime_delegate_for_active_context_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 = 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 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);

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)
Expand Down Expand Up @@ -1000,3 +1043,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_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_for_active_context_test(hostfxr, config_path, first_delegate_type, secondary_delegate_type, config_log_prefix, test_output);
}
4 changes: 4 additions & 0 deletions src/native/corehost/test/nativehost/host_context_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,8 @@ namespace host_context_test
int argc,
const pal::char_t *argv[],
pal::stringstream_t &test_output);
bool get_runtime_delegate_for_active_context(
const pal::string_t &hostfxr_path,
const pal::char_t *config_path,
pal::stringstream_t &test_output);
}
4 changes: 4 additions & 0 deletions src/native/corehost/test/nativehost/nativehost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_for_active_context")) == 0)
{
success = host_context_test::get_runtime_delegate_for_active_context(hostfxr_path, app_or_config_path, test_output);
}
else
{
std::cerr << "Invalid scenario" << std::endl;
Expand Down