struct corehost_context_contract
{
size_t version;
- context_handle instance;
int (*get_property_value)(
const char_t *key,
const char_t **value);
const char_t **values);
int (*load_runtime)();
int (*run_app)(
- const context_handle instance,
const int argc,
const char_t* argv[]);
int (*get_runtime_delegate)(
- const context_handle instance,
coreclr_delegate_type type,
void** delegate);
};
Contract for performing operations on an initialized hostpolicy.
* `version` - version of the struct.
-* `instance` - opaque handle to the `corehost_context_contract` state.
* `get_property_value` - function pointer for getting a property on the host context.
* `key` - key of the property to get.
* `value` - pointer to a buffer with the retrieved property value.
{
none = 0x0,
wait_for_initialized = 0x1,
+ get_contract = 0x2,
};
int corehost_initialize(const corehost_initialize_request_t *init_request, int32_t options, corehost_context_contract *context_contract)
```
-Initializes the host context. This calculates everything required to start CoreCLR (but does not actually do so).
+Initialize hostpolicy. This calculates everything required to start or attach to CoreCLR (but does not actually do so).
* `init_request` - struct containing information about the initialization request. If hostpolicy is not yet initialized, this is expected to be nullptr. If hostpolicy is already initialized, this should not be nullptr and this function will use the struct to check for compatibility with the way in which hostpolicy was previously initialized.
* `options` - initialization options
* `wait_for_initialized` - wait until initialization through a different request is completed
-* `context_contract` - if initialization is successful, this is populated with the contract for operating on the initialized host context.
+ * `get_contract` - get the contract for already initialized hostpolicy
+* `context_contract` - if initialization is successful, this is populated with the contract for operating on the initialized hostpolicy.
{
none = 0x0,
wait_for_initialized = 0x1, // Wait until initialization through a different request is completed
+ get_contract = 0x2, // Get the contract for the initialized hostpolicy
};
enum class coreclr_delegate_type
const host_context_t* fx_muxer_t::get_active_host_context()
{
std::lock_guard<std::mutex> lock{ g_context_lock };
+ if (g_active_host_context == nullptr)
+ return nullptr;
+
+ if (g_active_host_context->type == host_context_type::active)
+ return g_active_host_context.get();
+
+ if (g_active_host_context->type != host_context_type::empty)
+ return nullptr;
+
+ // Try to populate the contract for the 'empty' active context (i.e. created through non-context-based APIs)
+ const hostpolicy_contract_t &hostpolicy_contract = g_active_host_context->hostpolicy_contract;
+ if (hostpolicy_contract.initialize == nullptr)
+ {
+ trace::warning(_X("Getting the contract for the initialized hostpolicy is only supprted for .NET Core 3.0 or a higher version."));
+ return nullptr;
+ }
+
+ corehost_context_contract hostpolicy_context_contract;
+ {
+ propagate_error_writer_t propagate_error_writer_to_corehost(hostpolicy_contract.set_error_writer);
+ int rc = hostpolicy_contract.initialize(nullptr, intialization_options_t::get_contract, &hostpolicy_context_contract);
+ if (rc != StatusCode::Success)
+ {
+ trace::error(_X("Failed to get contract for existing initialized hostpolicy: 0x%x"), rc);
+ return nullptr;
+ }
+ }
+
+ // Set the hostpolicy context contract on the active host context and mark it as active
+ g_active_host_context->hostpolicy_context_contract = hostpolicy_context_contract;
+ g_active_host_context->type = host_context_type::active;
return g_active_host_context.get();
}
host_context_type type;
const hostpolicy_contract_t hostpolicy_contract;
- const corehost_context_contract hostpolicy_context_contract;
+ corehost_context_contract hostpolicy_context_contract;
// Whether or not the context was initialized for an app. argv will be empty for non-app contexts.
bool is_app;
if (host_context_handle == nullptr)
{
const host_context_t *context_maybe = fx_muxer_t::get_active_host_context();
- if (context_maybe == nullptr || context_maybe->type != host_context_type::active)
+ if (context_maybe == nullptr)
{
trace::error(_X("Hosting components context has not been initialized. Cannot get runtime properties."));
return StatusCode::HostInvalidState;
if (host_context_handle == nullptr)
{
const host_context_t *context_maybe = fx_muxer_t::get_active_host_context();
- if (context_maybe == nullptr || context_maybe->type != host_context_type::active)
+ if (context_maybe == nullptr)
{
trace::error(_X("Hosting components context has not been initialized. Cannot get runtime properties."));
return StatusCode::HostInvalidState;
return StatusCode::InvalidArgFailure;
bool wait_for_initialized = (options & intialization_options_t::wait_for_initialized) != 0;
+ bool get_contract = (options & intialization_options_t::get_contract) != 0;
+ if (wait_for_initialized && get_contract)
+ {
+ trace::error(_X("Specifying both initialization options for wait_for_initialized and get_contract is not allowed"));
+ return StatusCode::InvalidArgFailure;
+ }
+ if (get_contract)
+ {
+ if (init_request != nullptr)
+ {
+ trace::error(_X("Initialization request is expected to be null when getting the already initialized contract"));
+ return StatusCode::InvalidArgFailure;
+ }
+ }
+ else
{
std::unique_lock<std::mutex> lock { g_context_lock };
bool already_initializing = g_context_initializing.load();
rc = StatusCode::Success_HostAlreadyInitialized;
}
+ else if (get_contract)
+ {
+ const hostpolicy_context_t *context = get_hostpolicy_context(/*require_runtime*/ true);
+ if (context == nullptr)
+ {
+ trace::error(_X("Option to get the contract for the initialized hostpolicy was set, but hostpolicy has not been initialized"));
+ return StatusCode::HostInvalidState;
+ }
+
+ rc = StatusCode::Success;
+ }
else
{
rc = create_hostpolicy_context(g_init, args, g_init.host_mode != host_mode_t::libhost);
[InlineData(Scenario.NonContextMixed, CheckProperties.Set)]
[InlineData(Scenario.NonContextMixed, CheckProperties.Remove)]
[InlineData(Scenario.NonContextMixed, CheckProperties.GetAll)]
- // [InlineData(Scenario.NonContextMixed, CheckProperties.GetActive)] // TODO: https://github.com/dotnet/core-setup/issues/6197
- // [InlineData(Scenario.NonContextMixed, CheckProperties.GetAllActive)] // TODO: https://github.com/dotnet/core-setup/issues/6197
+ [InlineData(Scenario.NonContextMixed, CheckProperties.GetActive)]
+ [InlineData(Scenario.NonContextMixed, CheckProperties.GetAllActive)]
public void RunApp_GetDelegate(string scenario, string checkProperties)
{
if (scenario != Scenario.Mixed && scenario != Scenario.NonContextMixed)