示例#1
0
int run(const arguments_t& args, const pal::string_t& clr_path)
{
    // Load the deps resolver
    deps_resolver_t resolver(args);
    if (!resolver.valid())
    {
        trace::error(_X("Invalid .deps file"));
        return StatusCode::ResolverInitFailure;
    }

    // Add packages directory
    pal::string_t packages_dir = args.nuget_packages;
    if (!pal::directory_exists(packages_dir))
    {
        (void)pal::get_default_packages_directory(&packages_dir);
    }
    trace::info(_X("Package directory: %s"), packages_dir.empty() ? _X("not specified") : packages_dir.c_str());

    probe_paths_t probe_paths;
    if (!resolver.resolve_probe_paths(args.app_dir, packages_dir, args.dotnet_packages_cache, clr_path, &probe_paths))
    {
        return StatusCode::ResolverResolveFailure;
    }

    // Build CoreCLR properties
    const char* property_keys[] = {
        "TRUSTED_PLATFORM_ASSEMBLIES",
        "APP_PATHS",
        "APP_NI_PATHS",
        "NATIVE_DLL_SEARCH_DIRECTORIES",
        "PLATFORM_RESOURCE_ROOTS",
        "AppDomainCompatSwitch",
        // TODO: pipe this from corehost.json
        "SERVER_GC",
    };

    auto tpa_paths_cstr = pal::to_stdstring(probe_paths.tpa);
    auto app_base_cstr = pal::to_stdstring(args.app_dir);
    auto native_dirs_cstr = pal::to_stdstring(probe_paths.native);
    auto culture_dirs_cstr = pal::to_stdstring(probe_paths.culture);

    // Workaround for dotnet/cli Issue #488 and #652
    pal::string_t server_gc;
    std::string server_gc_cstr = (pal::getenv(_X("COREHOST_SERVER_GC"), &server_gc) && !server_gc.empty()) ? pal::to_stdstring(server_gc) : "1";

    const char* property_values[] = {
        // TRUSTED_PLATFORM_ASSEMBLIES
        tpa_paths_cstr.c_str(),
        // APP_PATHS
        app_base_cstr.c_str(),
        // APP_NI_PATHS
        app_base_cstr.c_str(),
        // NATIVE_DLL_SEARCH_DIRECTORIES
        native_dirs_cstr.c_str(),
        // PLATFORM_RESOURCE_ROOTS
        culture_dirs_cstr.c_str(),
        // AppDomainCompatSwitch
        "UseLatestBehaviorWhenTFMNotSpecified",
        // SERVER_GC
        server_gc_cstr.c_str(),
    };

    size_t property_size = sizeof(property_keys) / sizeof(property_keys[0]);

    // Bind CoreCLR
    if (!coreclr::bind(clr_path))
    {
        trace::error(_X("Failed to bind to coreclr"));
        return StatusCode::CoreClrBindFailure;
    }

    // Verbose logging
    if (trace::is_enabled())
    {
        for (size_t i = 0; i < property_size; ++i)
        {
            pal::string_t key, val;
            pal::to_palstring(property_keys[i], &key);
            pal::to_palstring(property_values[i], &val);
            trace::verbose(_X("Property %s = %s"), key.c_str(), val.c_str());
        }
    }

    std::string own_path;
    pal::to_stdstring(args.own_path.c_str(), &own_path);

    // Initialize CoreCLR
    coreclr::host_handle_t host_handle;
    coreclr::domain_id_t domain_id;
    auto hr = coreclr::initialize(
        own_path.c_str(),
        "clrhost",
        property_keys,
        property_values,
        property_size,
        &host_handle,
        &domain_id);
    if (!SUCCEEDED(hr))
    {
        trace::error(_X("Failed to initialize CoreCLR, HRESULT: 0x%X"), hr);
        return StatusCode::CoreClrInitFailure;
    }

    if (trace::is_enabled())
    {
        pal::string_t arg_str;
        for (int i = 0; i < args.app_argc; i++)
        {
            arg_str.append(args.app_argv[i]);
            arg_str.append(_X(","));
        }
        trace::info(_X("Launch host: %s app: %s, argc: %d args: %s"), args.own_path.c_str(),
            args.managed_application.c_str(), args.app_argc, arg_str.c_str());
    }

    // Initialize with empty strings
    std::vector<std::string> argv_strs(args.app_argc);
    std::vector<const char*> argv(args.app_argc);
    for (int i = 0; i < args.app_argc; i++)
    {
        pal::to_stdstring(args.app_argv[i], &argv_strs[i]);
        argv[i] = argv_strs[i].c_str();
    }

    std::string managed_app = pal::to_stdstring(args.managed_application);

    // Execute the application
    unsigned int exit_code = 1;
    hr = coreclr::execute_assembly(
        host_handle,
        domain_id,
        argv.size(),
        argv.data(),
        managed_app.c_str(),
        &exit_code);
    if (!SUCCEEDED(hr))
    {
        trace::error(_X("Failed to execute managed app, HRESULT: 0x%X"), hr);
        return StatusCode::CoreClrExeFailure;
    }

    // Shut down the CoreCLR
    hr = coreclr::shutdown(host_handle, domain_id);
    if (!SUCCEEDED(hr))
    {
        trace::warning(_X("Failed to shut down CoreCLR, HRESULT: 0x%X"), hr);
    }

    coreclr::unload();

    return exit_code;
}
示例#2
0
int run(const arguments_t& args)
{
    // Load the deps resolver
    deps_resolver_t resolver(g_init, args);

    pal::string_t resolver_errors;
    if (!resolver.valid(&resolver_errors))
    {
        trace::error(_X("Error initializing the dependency resolver: %s"), resolver_errors.c_str());
        return StatusCode::ResolverInitFailure;
    }

    // Setup breadcrumbs
    pal::string_t policy_name = _STRINGIFY(HOST_POLICY_PKG_NAME);
    pal::string_t policy_version = _STRINGIFY(HOST_POLICY_PKG_VER);

    // Always insert the hostpolicy that the code is running on.
    std::unordered_set<pal::string_t> breadcrumbs;
    breadcrumbs.insert(policy_name);
    breadcrumbs.insert(policy_name + _X(",") + policy_version);

    probe_paths_t probe_paths;
    if (!resolver.resolve_probe_paths(&probe_paths, &breadcrumbs))
    {
        return StatusCode::ResolverResolveFailure;
    }

    pal::string_t clr_path = probe_paths.coreclr;
    if (clr_path.empty() || !pal::realpath(&clr_path))
    {
        trace::error(_X("Could not resolve CoreCLR path. For more details, enable tracing by setting COREHOST_TRACE environment variable to 1"));;
        return StatusCode::CoreClrResolveFailure;
    }

    pal::string_t clrjit_path = probe_paths.clrjit;
    if (clrjit_path.empty())
    {
        trace::warning(_X("Could not resolve CLRJit path"));
    }
    else if (pal::realpath(&clrjit_path))
    {
        trace::verbose(_X("The resolved JIT path is '%s'"), clrjit_path.c_str());
    }
    else
    {
        clrjit_path.clear();
        trace::warning(_X("Could not resolve symlink to CLRJit path '%s'"), probe_paths.clrjit.c_str());
    }

    // Build CoreCLR properties
    std::vector<const char*> property_keys = {
        "TRUSTED_PLATFORM_ASSEMBLIES",
        "NATIVE_DLL_SEARCH_DIRECTORIES",
        "PLATFORM_RESOURCE_ROOTS",
        "AppDomainCompatSwitch",
        // Workaround: mscorlib does not resolve symlinks for AppContext.BaseDirectory dotnet/coreclr/issues/2128
        "APP_CONTEXT_BASE_DIRECTORY",
        "APP_CONTEXT_DEPS_FILES",
        "FX_DEPS_FILE"
    };

    // Note: these variables' lifetime should be longer than coreclr_initialize.
    std::vector<char> tpa_paths_cstr, app_base_cstr, native_dirs_cstr, resources_dirs_cstr, fx_deps, deps, clrjit_path_cstr;
    pal::pal_clrstring(probe_paths.tpa, &tpa_paths_cstr);
    pal::pal_clrstring(args.app_dir, &app_base_cstr);
    pal::pal_clrstring(probe_paths.native, &native_dirs_cstr);
    pal::pal_clrstring(probe_paths.resources, &resources_dirs_cstr);

    pal::pal_clrstring(resolver.get_fx_deps_file(), &fx_deps);
    pal::pal_clrstring(resolver.get_deps_file() + _X(";") + resolver.get_fx_deps_file(), &deps);

    std::vector<const char*> property_values = {
        // TRUSTED_PLATFORM_ASSEMBLIES
        tpa_paths_cstr.data(),
        // NATIVE_DLL_SEARCH_DIRECTORIES
        native_dirs_cstr.data(),
        // PLATFORM_RESOURCE_ROOTS
        resources_dirs_cstr.data(),
        // AppDomainCompatSwitch
        "UseLatestBehaviorWhenTFMNotSpecified",
        // APP_CONTEXT_BASE_DIRECTORY
        app_base_cstr.data(),
        // APP_CONTEXT_DEPS_FILES,
        deps.data(),
        // FX_DEPS_FILE
        fx_deps.data()
    };

    if (!clrjit_path.empty())
    {
        pal::pal_clrstring(clrjit_path, &clrjit_path_cstr);
        property_keys.push_back("JIT_PATH");
        property_values.push_back(clrjit_path_cstr.data());
    }

    bool set_app_paths = false;

    // Runtime options config properties.
    for (int i = 0; i < g_init.cfg_keys.size(); ++i)
    {
        // Provide opt-in compatible behavior by using the switch to set APP_PATHS
        if (pal::cstrcasecmp(g_init.cfg_keys[i].data(), "Microsoft.NETCore.DotNetHostPolicy.SetAppPaths") == 0)
        {
            set_app_paths = (pal::cstrcasecmp(g_init.cfg_values[i].data(), "true") == 0);
        }

        property_keys.push_back(g_init.cfg_keys[i].data());
        property_values.push_back(g_init.cfg_values[i].data());
    }

    // App paths and App NI paths
    if (set_app_paths)
    {
        property_keys.push_back("APP_PATHS");
        property_keys.push_back("APP_NI_PATHS");
        property_values.push_back(app_base_cstr.data());
        property_values.push_back(app_base_cstr.data());
    }

    size_t property_size = property_keys.size();
    assert(property_keys.size() == property_values.size());

    // Add API sets to the process DLL search
    pal::setup_api_sets(resolver.get_api_sets());

    // Bind CoreCLR
    pal::string_t clr_dir = get_directory(clr_path);
    trace::verbose(_X("CoreCLR path = '%s', CoreCLR dir = '%s'"), clr_path.c_str(), clr_dir.c_str());
    if (!coreclr::bind(clr_dir))
    {
        trace::error(_X("Failed to bind to CoreCLR at '%s'"), clr_path.c_str());
        return StatusCode::CoreClrBindFailure;
    }

    // Verbose logging
    if (trace::is_enabled())
    {
        for (size_t i = 0; i < property_size; ++i)
        {
            pal::string_t key, val;
            pal::clr_palstring(property_keys[i], &key);
            pal::clr_palstring(property_values[i], &val);
            trace::verbose(_X("Property %s = %s"), key.c_str(), val.c_str());
        }
    }

    std::vector<char> own_path;
    pal::pal_clrstring(args.own_path, &own_path);

    // Initialize CoreCLR
    coreclr::host_handle_t host_handle;
    coreclr::domain_id_t domain_id;
    auto hr = coreclr::initialize(
        own_path.data(),
        "clrhost",
        property_keys.data(),
        property_values.data(),
        property_size,
        &host_handle,
        &domain_id);
    if (!SUCCEEDED(hr))
    {
        trace::error(_X("Failed to initialize CoreCLR, HRESULT: 0x%X"), hr);
        return StatusCode::CoreClrInitFailure;
    }

    // Initialize clr strings for arguments
    std::vector<std::vector<char>> argv_strs(args.app_argc);
    std::vector<const char*> argv(args.app_argc);
    for (int i = 0; i < args.app_argc; i++)
    {
        pal::pal_clrstring(args.app_argv[i], &argv_strs[i]);
        argv[i] = argv_strs[i].data();
    }

    if (trace::is_enabled())
    {
        pal::string_t arg_str;
        for (int i = 0; i < argv.size(); i++)
        {
            pal::string_t cur;
            pal::clr_palstring(argv[i], &cur);
            arg_str.append(cur);
            arg_str.append(_X(","));
        }
        trace::info(_X("Launch host: %s, app: %s, argc: %d, args: %s"), args.own_path.c_str(),
            args.managed_application.c_str(), args.app_argc, arg_str.c_str());
    }

    std::vector<char> managed_app;
    pal::pal_clrstring(args.managed_application, &managed_app);

    // Leave breadcrumbs for servicing.
    breadcrumb_writer_t writer(&breadcrumbs);
    writer.begin_write();

    // Previous hostpolicy trace messages must be printed before executing assembly
    trace::flush();

    // Execute the application
    unsigned int exit_code = 1;
    hr = coreclr::execute_assembly(
        host_handle,
        domain_id,
        argv.size(),
        argv.data(),
        managed_app.data(),
        &exit_code);

    if (!SUCCEEDED(hr))
    {
        trace::error(_X("Failed to execute managed app, HRESULT: 0x%X"), hr);
        return StatusCode::CoreClrExeFailure;
    }

    // Shut down the CoreCLR
    hr = coreclr::shutdown(host_handle, domain_id);
    if (!SUCCEEDED(hr))
    {
        trace::warning(_X("Failed to shut down CoreCLR, HRESULT: 0x%X"), hr);
    }

    coreclr::unload();

    // Finish breadcrumb writing
    writer.end_write();

    return exit_code;
}