diff options
| author | Robert Schumacher <roschuma@microsoft.com> | 2020-03-19 17:15:54 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-03-19 17:15:54 -0700 |
| commit | 8b201cb43c5bb1fd976e1deac2154b0ab64c5e10 (patch) | |
| tree | 2bbfc01905568ac7c6cd40ab0952485f0328731a /toolsrc/src | |
| parent | 2c2e67f35fb5af7168dc800ab82e59fdcba0e9c2 (diff) | |
| parent | 26949af8f8ae311e94198c8c1bd2d93578809630 (diff) | |
| download | vcpkg-8b201cb43c5bb1fd976e1deac2154b0ab64c5e10.tar.gz vcpkg-8b201cb43c5bb1fd976e1deac2154b0ab64c5e10.zip | |
Merge pull request #10372 from ras0219-msft/dev/roschuma/jobs
[vcpkg] Introduce Job Objects to improve ctrl-c performance on Windows
Diffstat (limited to 'toolsrc/src')
| -rw-r--r-- | toolsrc/src/vcpkg.cpp | 3 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg/base/system.process.cpp | 38 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg/commands.env.cpp | 31 |
3 files changed, 60 insertions, 12 deletions
diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 1f212dd94..c2ee42200 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -269,7 +269,7 @@ int wmain(int, const wchar_t* const* const); #include <shellapi.h> int main(int argc, const char* const* const /*argv*/) { - wchar_t **wargv; + wchar_t** wargv; wargv = CommandLineToArgvW(GetCommandLineW(), &argc); return wmain(argc, wargv); } @@ -292,6 +292,7 @@ int main(const int argc, const char* const* const argv) SetConsoleCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8); + System::initialize_global_job_object(); #endif Checks::register_global_shutdown_handler([]() { diff --git a/toolsrc/src/vcpkg/base/system.process.cpp b/toolsrc/src/vcpkg/base/system.process.cpp index 076a1edba..bba29a2d7 100644 --- a/toolsrc/src/vcpkg/base/system.process.cpp +++ b/toolsrc/src/vcpkg/base/system.process.cpp @@ -30,7 +30,7 @@ namespace vcpkg { struct CtrlCStateMachine { - CtrlCStateMachine() : m_number_of_external_processes(0) {} + CtrlCStateMachine() : m_number_of_external_processes(0), m_global_job(NULL), m_in_interactive(0) {} void transition_to_spawn_process() noexcept { @@ -91,17 +91,47 @@ namespace vcpkg } else { - // We are currently blocked on a child process. Upon return, transition_from_spawn_process() - // will be called and exit. + // We are currently blocked on a child process. + // If none of the child processes are interactive, use the Job Object to terminate the tree. + if (m_in_interactive.load() == 0) + { + auto job = m_global_job.exchange(NULL); + if (job != NULL) + { + ::CloseHandle(job); + } + } } } + void initialize_job() + { + m_global_job = CreateJobObjectW(NULL, NULL); + if (m_global_job != NULL) + { + JOBOBJECT_EXTENDED_LIMIT_INFORMATION info = {}; + info.BasicLimitInformation.LimitFlags = + JOB_OBJECT_LIMIT_BREAKAWAY_OK | JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; + ::SetInformationJobObject(m_global_job, JobObjectExtendedLimitInformation, &info, sizeof(info)); + ::AssignProcessToJobObject(m_global_job, ::GetCurrentProcess()); + } + } + + void enter_interactive() { ++m_in_interactive; } + void exit_interactive() { --m_in_interactive; } + private: std::atomic<int> m_number_of_external_processes; + std::atomic<HANDLE> m_global_job; + std::atomic<int> m_in_interactive; }; static CtrlCStateMachine g_ctrl_c_state; } + + void System::initialize_global_job_object() { g_ctrl_c_state.initialize_job(); } + void System::enter_interactive_subprocess() { g_ctrl_c_state.enter_interactive(); } + void System::exit_interactive_subprocess() { g_ctrl_c_state.exit_interactive(); } #endif fs::path System::get_exe_path_of_current_process() @@ -428,7 +458,7 @@ namespace vcpkg { auto timer = Chrono::ElapsedTimer::create_started(); - auto process_info = windows_create_process(cmd_line, {}, DETACHED_PROCESS); + auto process_info = windows_create_process(cmd_line, {}, DETACHED_PROCESS | CREATE_BREAKAWAY_FROM_JOB); if (auto p = process_info.get()) { p->close_handles(); diff --git a/toolsrc/src/vcpkg/commands.env.cpp b/toolsrc/src/vcpkg/commands.env.cpp index 5b673b965..ca398068f 100644 --- a/toolsrc/src/vcpkg/commands.env.cpp +++ b/toolsrc/src/vcpkg/commands.env.cpp @@ -48,7 +48,7 @@ namespace vcpkg::Commands::Env const Build::PreBuildInfo pre_build_info( paths, triplet, var_provider.get_generic_triplet_vars(triplet).value_or_exit(VCPKG_LINE_INFO)); const Toolset& toolset = paths.get_toolset(pre_build_info); - auto env_cmd = Build::make_build_env_cmd(pre_build_info, toolset); + auto build_env_cmd = Build::make_build_env_cmd(pre_build_info, toolset); std::unordered_map<std::string, std::string> extra_env = {}; const bool add_bin = Util::Sets::contains(options.switches, OPTION_BIN); @@ -74,12 +74,29 @@ namespace vcpkg::Commands::Env if (add_python) extra_env.emplace("PYTHONPATH", (paths.installed / triplet.to_string() / "python").u8string()); if (path_vars.size() > 0) extra_env.emplace("PATH", Strings::join(";", path_vars)); - std::string env_cmd_prefix = env_cmd.empty() ? "" : Strings::format("%s && ", env_cmd); - std::string env_cmd_suffix = - args.command_arguments.empty() ? "cmd" : Strings::format("cmd /c %s", args.command_arguments.at(0)); + auto env = [&] { + auto clean_env = System::get_modified_clean_environment(extra_env); + if (build_env_cmd.empty()) + return clean_env; + else + { +#ifdef _WIN32 + return System::cmd_execute_modify_env(build_env_cmd, clean_env); +#else + Checks::exit_with_message(VCPKG_LINE_INFO, + "Build environment commands are not supported on this platform"); +#endif + } + }(); - const std::string cmd = Strings::format("%s%s", env_cmd_prefix, env_cmd_suffix); - System::cmd_execute(cmd, System::get_modified_clean_environment(extra_env)); - Checks::exit_success(VCPKG_LINE_INFO); + std::string cmd = args.command_arguments.empty() ? "cmd" : ("cmd /c " + args.command_arguments.at(0)); +#ifdef _WIN32 + System::enter_interactive_subprocess(); +#endif + auto rc = System::cmd_execute(cmd, env); +#ifdef _WIN32 + System::exit_interactive_subprocess(); +#endif + Checks::exit_with_code(VCPKG_LINE_INFO, rc); } } |
