From 2b8e72944703d2b391975069d971098899fdf874 Mon Sep 17 00:00:00 2001 From: "U-olece-PC\\olece" Date: Fri, 4 Dec 2015 14:04:40 +0100 Subject: [PATCH] Fixes to windows processing and some general processing issues. --- src/CMakeLists.txt | 2 +- src/process.cc | 2 +- src/process.h | 2 +- src/process_win.cc | 69 ++++++++++++++++++++++++++++++++++------------ 4 files changed, 54 insertions(+), 21 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b81bca4..67eeecc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,7 +22,7 @@ if(UNIX) #Checking if compiling on Ubuntu that has a buggy menu system endif() if(MSYS) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DJUCI_CMAKE_INSTALL_PREFIX=\\\"${CMAKE_INSTALL_PREFIX}\\\"") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMSYS2_PROCESS_USE_SH -DJUCI_CMAKE_INSTALL_PREFIX=\\\"${CMAKE_INSTALL_PREFIX}\\\"") endif() INCLUDE(FindPkgConfig) diff --git a/src/process.cc b/src/process.cc index 7e20fe6..2391ab3 100644 --- a/src/process.cc +++ b/src/process.cc @@ -9,7 +9,7 @@ Process::Process(const std::string &command, const std::string &path, bool use_stdin, size_t buffer_size): read_stdout(read_stdout), read_stderr(read_stderr), use_stdin(use_stdin), buffer_size(buffer_size) { id=open(command, path); - if(id>0) + if(id!=0) async_read(); } diff --git a/src/process.h b/src/process.h index ca05c64..66019b1 100644 --- a/src/process.h +++ b/src/process.h @@ -8,7 +8,7 @@ #include #ifdef _WIN32 #include - typedef HANDLE process_id_type; + typedef DWORD process_id_type; typedef HANDLE file_descriptor_type; #else #include diff --git a/src/process_win.cc b/src/process_win.cc index 5fa2e38..771c377 100644 --- a/src/process_win.cc +++ b/src/process_win.cc @@ -1,5 +1,6 @@ #include "process.h" #include +#include "TlHelp32.h" #include //TODO: remove using namespace std; //TODO: remove @@ -30,25 +31,25 @@ process_id_type Process::open(const std::string &command, const std::string &pat if(stdin_fd) { if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) - return NULL; + return 0; if(!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0)) { CloseHandle(g_hChildStd_IN_Rd); CloseHandle(g_hChildStd_IN_Wr); - return NULL; + return 0; } } if(stdout_fd) { if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) { if(stdin_fd) CloseHandle(g_hChildStd_IN_Rd); if(stdin_fd) CloseHandle(g_hChildStd_IN_Wr); - return NULL; + return 0; } if(!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) { if(stdin_fd) CloseHandle(g_hChildStd_IN_Rd); if(stdin_fd) CloseHandle(g_hChildStd_IN_Wr); CloseHandle(g_hChildStd_OUT_Rd); CloseHandle(g_hChildStd_OUT_Wr); - return NULL; + return 0; } } if(stderr_fd) { @@ -57,7 +58,7 @@ process_id_type Process::open(const std::string &command, const std::string &pat if(stdin_fd) CloseHandle(g_hChildStd_IN_Wr); if(stdout_fd) CloseHandle(g_hChildStd_OUT_Rd); if(stdout_fd) CloseHandle(g_hChildStd_OUT_Wr); - return NULL; + return 0; } if(!SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0)) { if(stdin_fd) CloseHandle(g_hChildStd_IN_Rd); @@ -66,7 +67,7 @@ process_id_type Process::open(const std::string &command, const std::string &pat if(stdout_fd) CloseHandle(g_hChildStd_OUT_Wr); CloseHandle(g_hChildStd_ERR_Rd); CloseHandle(g_hChildStd_ERR_Wr); - return NULL; + return 0; } } @@ -90,8 +91,27 @@ process_id_type Process::open(const std::string &command, const std::string &pat path_ptr=new char[path.size()+1]; std::strcpy(path_ptr, path.c_str()); } - char* command_cstr=new char[command.size()+1]; + + char* command_cstr; +#ifdef MSYS2_PROCESS_USE_SH + size_t pos=0; + std::string sh_command=command; + while((pos=sh_command.find('\"', pos))!=std::string::npos) { + if(pos>0 && sh_command[pos-1]!='\\') { + sh_command.replace(pos, 1, "\\\""); + pos++; + } + pos++; + } + sh_command.insert(0, "sh -c \""); + sh_command+="\""; + command_cstr=new char[sh_command.size()+1]; + std::strcpy(command_cstr, sh_command.c_str()); +#else + command_cstr=new char[command.size()+1]; std::strcpy(command_cstr, command.c_str()); +#endif + BOOL bSuccess = CreateProcess(NULL, command_cstr, // command line NULL, // process security attributes @@ -109,13 +129,9 @@ process_id_type Process::open(const std::string &command, const std::string &pat if(stdin_fd) CloseHandle(g_hChildStd_IN_Rd); if(stdout_fd) CloseHandle(g_hChildStd_OUT_Wr); if(stderr_fd) CloseHandle(g_hChildStd_ERR_Wr); - return NULL; + return 0; } else { - // Close handles to the child process and its primary thread. - // Some applications might keep these handles to monitor the status - // of the child process, for example. - CloseHandle(process_info.hThread); if(stdin_fd) CloseHandle(g_hChildStd_IN_Rd); if(stdout_fd) CloseHandle(g_hChildStd_OUT_Wr); @@ -125,7 +141,8 @@ process_id_type Process::open(const std::string &command, const std::string &pat if(stdin_fd) *stdin_fd=g_hChildStd_IN_Wr; if(stdout_fd) *stdout_fd=g_hChildStd_OUT_Rd; if(stderr_fd) *stderr_fd=g_hChildStd_ERR_Rd; - return process_info.hProcess; + + return process_info.dwProcessId; } void Process::async_read() { @@ -157,9 +174,10 @@ void Process::async_read() { int Process::get_exit_code() { DWORD exit_code; - WaitForSingleObject(id, INFINITE); - GetExitCodeProcess(id, &exit_code); - CloseHandle(id); + HANDLE process_info = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id); + WaitForSingleObject(process_info, INFINITE); + GetExitCodeProcess(process_info, &exit_code); + CloseHandle(process_info); if(stdout_thread.joinable()) stdout_thread.join(); @@ -188,7 +206,7 @@ bool Process::write(const char *bytes, size_t n) { stdin_mutex.lock(); if(stdin_fd) { DWORD written; - BOOL bSuccess=WriteFile(id, bytes, static_cast(n), &written, NULL); + BOOL bSuccess=WriteFile(*stdin_fd, bytes, static_cast(n), &written, NULL); if(!bSuccess || written==0) { stdin_mutex.unlock(); return false; @@ -203,5 +221,20 @@ bool Process::write(const char *bytes, size_t n) { } void Process::kill(process_id_type id, bool force) { - TerminateProcess(id, 2); + HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if(snapshot) { + PROCESSENTRY32 process; + ZeroMemory(&process, sizeof(process)); + process.dwSize = sizeof(process); + if(Process32First(snapshot, &process)) { + do { + if(process.th32ParentProcessID==id) { + HANDLE process_info = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID); + if(process_info) TerminateProcess(process_info, 2); + } + } while (Process32Next(snapshot, &process)); + } + } + HANDLE process_info = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id); + if(process_info) TerminateProcess(process_info, 2); }