mirror of https://gitlab.com/cppit/jucipp
6 changed files with 7 additions and 575 deletions
@ -1,25 +0,0 @@ |
|||||||
#include "process.hpp" |
|
||||||
|
|
||||||
#include <iostream> //TODO: remove |
|
||||||
using namespace std; //TODO: remove
|
|
||||||
|
|
||||||
Process::Process(const std::string &command, const std::string &path, |
|
||||||
std::function<void(const char* bytes, size_t n)> read_stdout, |
|
||||||
std::function<void(const char* bytes, size_t n)> read_stderr, |
|
||||||
bool open_stdin, size_t buffer_size): |
|
||||||
closed(true), read_stdout(read_stdout), read_stderr(read_stderr), open_stdin(open_stdin), buffer_size(buffer_size) { |
|
||||||
open(command, path); |
|
||||||
async_read(); |
|
||||||
} |
|
||||||
|
|
||||||
Process::~Process() { |
|
||||||
close_fds(); |
|
||||||
} |
|
||||||
|
|
||||||
Process::id_type Process::get_id() { |
|
||||||
return data.id; |
|
||||||
} |
|
||||||
|
|
||||||
bool Process::write(const std::string &data) { |
|
||||||
return write(data.c_str(), data.size()); |
|
||||||
} |
|
||||||
@ -1,81 +0,0 @@ |
|||||||
#ifndef TINY_PROCESS_LIBRARY_HPP_ |
|
||||||
#define TINY_PROCESS_LIBRARY_HPP_ |
|
||||||
|
|
||||||
#include <string> |
|
||||||
#include <functional> |
|
||||||
#include <vector> |
|
||||||
#include <mutex> |
|
||||||
#include <thread> |
|
||||||
#include <mutex> |
|
||||||
#ifdef _WIN32 |
|
||||||
#include <windows.h> |
|
||||||
#else |
|
||||||
#include <sys/wait.h> |
|
||||||
#endif |
|
||||||
|
|
||||||
///Create a new process given command and run path.
|
|
||||||
///TODO: on Windows it is harder to specify which pipes to redirect.
|
|
||||||
///Thus, at the moment, if read_stdout==nullptr, read_stderr==nullptr and open_stdin==false,
|
|
||||||
///the stdout, stderr and stdin are sent to the parent process instead.
|
|
||||||
///Compile with -DMSYS_PROCESS_USE_SH to run command using "sh -c [command]" on Windows as well.
|
|
||||||
class Process { |
|
||||||
public: |
|
||||||
#ifdef _WIN32 |
|
||||||
typedef DWORD id_type; //Process id type
|
|
||||||
typedef HANDLE fd_type; //File descriptor type
|
|
||||||
#else |
|
||||||
typedef pid_t id_type; |
|
||||||
typedef int fd_type; |
|
||||||
#endif |
|
||||||
private: |
|
||||||
class Data { |
|
||||||
public: |
|
||||||
Data(); |
|
||||||
id_type id; |
|
||||||
#ifdef _WIN32 |
|
||||||
HANDLE handle; |
|
||||||
#endif |
|
||||||
}; |
|
||||||
public: |
|
||||||
Process(const std::string &command, const std::string &path=std::string(), |
|
||||||
std::function<void(const char *bytes, size_t n)> read_stdout=nullptr, |
|
||||||
std::function<void(const char *bytes, size_t n)> read_stderr=nullptr, |
|
||||||
bool open_stdin=false, |
|
||||||
size_t buffer_size=131072); |
|
||||||
~Process(); |
|
||||||
|
|
||||||
///Get the process id of the started process.
|
|
||||||
id_type get_id(); |
|
||||||
///Wait until process is finished, and return exit status.
|
|
||||||
int get_exit_status(); |
|
||||||
///Write to stdin.
|
|
||||||
bool write(const char *bytes, size_t n); |
|
||||||
///Write to stdin. Convenience function using write(const char *, size_t).
|
|
||||||
bool write(const std::string &data); |
|
||||||
///Close stdin. If the process takes parameters from stdin, use this to notify that all parameters have been sent.
|
|
||||||
void close_stdin(); |
|
||||||
|
|
||||||
///Kill the process.
|
|
||||||
void kill(bool force=false); |
|
||||||
///Kill a given process id. Use kill(bool force) instead if possible.
|
|
||||||
static void kill(id_type id, bool force=false); |
|
||||||
|
|
||||||
private: |
|
||||||
Data data; |
|
||||||
bool closed; |
|
||||||
std::mutex close_mutex; |
|
||||||
std::function<void(const char* bytes, size_t n)> read_stdout; |
|
||||||
std::function<void(const char* bytes, size_t n)> read_stderr; |
|
||||||
std::thread stdout_thread, stderr_thread; |
|
||||||
bool open_stdin; |
|
||||||
std::mutex stdin_mutex; |
|
||||||
const size_t buffer_size; |
|
||||||
|
|
||||||
std::unique_ptr<fd_type> stdout_fd, stderr_fd, stdin_fd; |
|
||||||
|
|
||||||
id_type open(const std::string &command, const std::string &path); |
|
||||||
void async_read(); |
|
||||||
void close_fds(); |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // TINY_PROCESS_LIBRARY_HPP_
|
|
||||||
@ -1,183 +0,0 @@ |
|||||||
#include "process.hpp" |
|
||||||
#include <cstdlib> |
|
||||||
#include <unistd.h> |
|
||||||
#include <signal.h> |
|
||||||
|
|
||||||
#include <iostream> //TODO: remove |
|
||||||
using namespace std; //TODO: remove
|
|
||||||
|
|
||||||
Process::Data::Data(): id(-1) {} |
|
||||||
|
|
||||||
Process::id_type Process::open(const std::string &command, const std::string &path) { |
|
||||||
if(open_stdin) |
|
||||||
stdin_fd=std::unique_ptr<fd_type>(new fd_type); |
|
||||||
if(read_stdout) |
|
||||||
stdout_fd=std::unique_ptr<fd_type>(new fd_type); |
|
||||||
if(read_stderr) |
|
||||||
stderr_fd=std::unique_ptr<fd_type>(new fd_type); |
|
||||||
|
|
||||||
int stdin_p[2], stdout_p[2], stderr_p[2]; |
|
||||||
|
|
||||||
if(stdin_fd && pipe(stdin_p)!=0) { |
|
||||||
close(stdin_p[0]); |
|
||||||
close(stdin_p[1]); |
|
||||||
return -1; |
|
||||||
} |
|
||||||
if(stdout_fd && pipe(stdout_p)!=0) { |
|
||||||
if(stdin_fd) close(stdin_p[0]); |
|
||||||
if(stdin_fd) close(stdin_p[1]); |
|
||||||
close(stdout_p[0]); |
|
||||||
close(stdout_p[1]); |
|
||||||
return -1; |
|
||||||
} |
|
||||||
if(stderr_fd && pipe(stderr_p)!=0) { |
|
||||||
if(stdin_fd) close(stdin_p[0]); |
|
||||||
if(stdin_fd) close(stdin_p[1]); |
|
||||||
if(stdout_fd) close(stdout_p[0]); |
|
||||||
if(stdout_fd) close(stdout_p[1]); |
|
||||||
close(stderr_p[0]); |
|
||||||
close(stderr_p[1]); |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
id_type pid = fork(); |
|
||||||
|
|
||||||
if (pid < 0) { |
|
||||||
if(stdin_fd) close(stdin_p[0]); |
|
||||||
if(stdin_fd) close(stdin_p[1]); |
|
||||||
if(stdout_fd) close(stdout_p[0]); |
|
||||||
if(stdout_fd) close(stdout_p[1]); |
|
||||||
if(stderr_fd) close(stderr_p[0]); |
|
||||||
if(stderr_fd) close(stderr_p[1]); |
|
||||||
return pid; |
|
||||||
} |
|
||||||
else if (pid == 0) { |
|
||||||
if(stdin_fd) close(stdin_p[1]); |
|
||||||
if(stdout_fd) close(stdout_p[0]); |
|
||||||
if(stderr_fd) close(stderr_p[0]); |
|
||||||
if(stdin_fd) dup2(stdin_p[0], 0); |
|
||||||
if(stdout_fd) dup2(stdout_p[1], 1); |
|
||||||
if(stderr_fd) dup2(stderr_p[1], 2); |
|
||||||
|
|
||||||
setpgid(0, 0); |
|
||||||
//TODO: See here on how to emulate tty for colors: http://stackoverflow.com/questions/1401002/trick-an-application-into-thinking-its-stdin-is-interactive-not-a-pipe
|
|
||||||
//TODO: One solution is: echo "command;exit"|script -q /dev/null
|
|
||||||
|
|
||||||
if(!path.empty()) |
|
||||||
execl("/bin/sh", "sh", "-c", ("cd \""+path+"\" && "+command).c_str(), NULL); |
|
||||||
else |
|
||||||
execl("/bin/sh", "sh", "-c", command.c_str(), NULL); |
|
||||||
|
|
||||||
_exit(EXIT_FAILURE); |
|
||||||
} |
|
||||||
|
|
||||||
if(stdin_fd) close(stdin_p[0]); |
|
||||||
if(stdout_fd) close(stdout_p[1]); |
|
||||||
if(stderr_fd) close(stderr_p[1]); |
|
||||||
|
|
||||||
if(stdin_fd) *stdin_fd = stdin_p[1]; |
|
||||||
if(stdout_fd) *stdout_fd = stdout_p[0]; |
|
||||||
if(stderr_fd) *stderr_fd = stderr_p[0]; |
|
||||||
|
|
||||||
closed=false; |
|
||||||
data.id=pid; |
|
||||||
return pid; |
|
||||||
} |
|
||||||
|
|
||||||
void Process::async_read() { |
|
||||||
if(data.id<=0) |
|
||||||
return; |
|
||||||
if(stdout_fd) { |
|
||||||
stdout_thread=std::thread([this](){ |
|
||||||
char buffer[buffer_size]; |
|
||||||
ssize_t n; |
|
||||||
while ((n=read(*stdout_fd, buffer, buffer_size)) > 0) |
|
||||||
read_stdout(buffer, static_cast<size_t>(n)); |
|
||||||
}); |
|
||||||
} |
|
||||||
if(stderr_fd) { |
|
||||||
stderr_thread=std::thread([this](){ |
|
||||||
char buffer[buffer_size]; |
|
||||||
ssize_t n; |
|
||||||
while ((n=read(*stderr_fd, buffer, buffer_size)) > 0) |
|
||||||
read_stderr(buffer, static_cast<size_t>(n)); |
|
||||||
}); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
int Process::get_exit_status() { |
|
||||||
if(data.id<=0) |
|
||||||
return -1; |
|
||||||
int exit_status; |
|
||||||
waitpid(data.id, &exit_status, 0); |
|
||||||
close_mutex.lock(); |
|
||||||
closed=true; |
|
||||||
close_mutex.unlock(); |
|
||||||
|
|
||||||
close_fds(); |
|
||||||
|
|
||||||
return exit_status; |
|
||||||
} |
|
||||||
|
|
||||||
void Process::close_fds() { |
|
||||||
if(stdout_thread.joinable()) |
|
||||||
stdout_thread.join(); |
|
||||||
if(stderr_thread.joinable()) |
|
||||||
stderr_thread.join(); |
|
||||||
|
|
||||||
if(stdin_fd) |
|
||||||
close_stdin(); |
|
||||||
if(stdout_fd) { |
|
||||||
close(*stdout_fd); |
|
||||||
stdout_fd.reset(); |
|
||||||
} |
|
||||||
if(stderr_fd) { |
|
||||||
close(*stderr_fd); |
|
||||||
stderr_fd.reset(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
bool Process::write(const char *bytes, size_t n) { |
|
||||||
stdin_mutex.lock(); |
|
||||||
if(stdin_fd) { |
|
||||||
if(::write(*stdin_fd, bytes, n)>=0) { |
|
||||||
stdin_mutex.unlock(); |
|
||||||
return true; |
|
||||||
} |
|
||||||
else { |
|
||||||
stdin_mutex.unlock(); |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
stdin_mutex.unlock(); |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
void Process::close_stdin() { |
|
||||||
stdin_mutex.lock(); |
|
||||||
if(stdin_fd) { |
|
||||||
close(*stdin_fd); |
|
||||||
stdin_fd.reset(); |
|
||||||
} |
|
||||||
stdin_mutex.unlock(); |
|
||||||
} |
|
||||||
|
|
||||||
void Process::kill(bool force) { |
|
||||||
close_mutex.lock(); |
|
||||||
if(data.id>0 && !closed) { |
|
||||||
if(force) |
|
||||||
::kill(-data.id, SIGTERM); |
|
||||||
else |
|
||||||
::kill(-data.id, SIGINT); |
|
||||||
} |
|
||||||
close_mutex.unlock(); |
|
||||||
} |
|
||||||
|
|
||||||
void Process::kill(id_type id, bool force) { |
|
||||||
if(id<=0) |
|
||||||
return; |
|
||||||
if(force) |
|
||||||
::kill(-id, SIGTERM); |
|
||||||
else |
|
||||||
::kill(-id, SIGINT); |
|
||||||
} |
|
||||||
@ -1,281 +0,0 @@ |
|||||||
#include "process.hpp" |
|
||||||
#include <cstring> |
|
||||||
#include "TlHelp32.h" |
|
||||||
|
|
||||||
#include <iostream> //TODO: remove |
|
||||||
using namespace std; //TODO: remove
|
|
||||||
|
|
||||||
Process::Data::Data(): id(0), handle(NULL) {} |
|
||||||
|
|
||||||
//Based on the example at https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx.
|
|
||||||
Process::id_type Process::open(const std::string &command, const std::string &path) { |
|
||||||
if(open_stdin) |
|
||||||
stdin_fd=std::unique_ptr<fd_type>(new fd_type); |
|
||||||
if(read_stdout) |
|
||||||
stdout_fd=std::unique_ptr<fd_type>(new fd_type); |
|
||||||
if(read_stderr) |
|
||||||
stderr_fd=std::unique_ptr<fd_type>(new fd_type); |
|
||||||
|
|
||||||
HANDLE g_hChildStd_IN_Rd = NULL; |
|
||||||
HANDLE g_hChildStd_IN_Wr = NULL; |
|
||||||
HANDLE g_hChildStd_OUT_Rd = NULL; |
|
||||||
HANDLE g_hChildStd_OUT_Wr = NULL; |
|
||||||
HANDLE g_hChildStd_ERR_Rd = NULL; |
|
||||||
HANDLE g_hChildStd_ERR_Wr = NULL; |
|
||||||
|
|
||||||
SECURITY_ATTRIBUTES saAttr; |
|
||||||
|
|
||||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); |
|
||||||
saAttr.bInheritHandle = TRUE; |
|
||||||
saAttr.lpSecurityDescriptor = NULL; |
|
||||||
|
|
||||||
if(stdin_fd) { |
|
||||||
if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) |
|
||||||
return 0; |
|
||||||
if(!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0)) { |
|
||||||
CloseHandle(g_hChildStd_IN_Rd); |
|
||||||
CloseHandle(g_hChildStd_IN_Wr); |
|
||||||
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 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 0; |
|
||||||
} |
|
||||||
} |
|
||||||
if(stderr_fd) { |
|
||||||
if (!CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &saAttr, 0)) { |
|
||||||
if(stdin_fd) CloseHandle(g_hChildStd_IN_Rd); |
|
||||||
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 0; |
|
||||||
} |
|
||||||
if(!SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0)) { |
|
||||||
if(stdin_fd) CloseHandle(g_hChildStd_IN_Rd); |
|
||||||
if(stdin_fd) CloseHandle(g_hChildStd_IN_Wr); |
|
||||||
if(stdout_fd) CloseHandle(g_hChildStd_OUT_Rd); |
|
||||||
if(stdout_fd) CloseHandle(g_hChildStd_OUT_Wr); |
|
||||||
CloseHandle(g_hChildStd_ERR_Rd); |
|
||||||
CloseHandle(g_hChildStd_ERR_Wr); |
|
||||||
return 0; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
PROCESS_INFORMATION process_info; |
|
||||||
STARTUPINFO siStartInfo; |
|
||||||
|
|
||||||
ZeroMemory(&process_info, sizeof(PROCESS_INFORMATION)); |
|
||||||
|
|
||||||
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); |
|
||||||
siStartInfo.cb = sizeof(STARTUPINFO); |
|
||||||
if(stdin_fd) siStartInfo.hStdInput = g_hChildStd_IN_Rd; |
|
||||||
if(stdout_fd) siStartInfo.hStdOutput = g_hChildStd_OUT_Wr; |
|
||||||
if(stderr_fd) siStartInfo.hStdError = g_hChildStd_ERR_Wr; |
|
||||||
if(stdin_fd || stdout_fd || stderr_fd) |
|
||||||
siStartInfo.dwFlags |= STARTF_USESTDHANDLES; |
|
||||||
|
|
||||||
char* path_cstr; |
|
||||||
if(path=="") |
|
||||||
path_cstr=NULL; |
|
||||||
else { |
|
||||||
path_cstr=new char[path.size()+1]; |
|
||||||
std::strcpy(path_cstr, path.c_str()); |
|
||||||
} |
|
||||||
|
|
||||||
char* command_cstr; |
|
||||||
#ifdef MSYS_PROCESS_USE_SH |
|
||||||
size_t pos=0; |
|
||||||
std::string sh_command=command; |
|
||||||
while((pos=sh_command.find('\\', pos))!=std::string::npos) { |
|
||||||
sh_command.replace(pos, 1, "\\\\\\\\"); |
|
||||||
pos+=4; |
|
||||||
} |
|
||||||
pos=0; |
|
||||||
while((pos=sh_command.find('\"', pos))!=std::string::npos) { |
|
||||||
sh_command.replace(pos, 1, "\\\""); |
|
||||||
pos+=2; |
|
||||||
} |
|
||||||
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, NULL, NULL, TRUE, 0, |
|
||||||
NULL, path_cstr, &siStartInfo, &process_info); |
|
||||||
delete[] path_cstr; |
|
||||||
delete[] command_cstr; |
|
||||||
|
|
||||||
if(!bSuccess) { |
|
||||||
CloseHandle(process_info.hProcess); |
|
||||||
CloseHandle(process_info.hThread); |
|
||||||
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 0; |
|
||||||
} |
|
||||||
else { |
|
||||||
CloseHandle(process_info.hThread); |
|
||||||
if(stdin_fd) CloseHandle(g_hChildStd_IN_Rd); |
|
||||||
if(stdout_fd) CloseHandle(g_hChildStd_OUT_Wr); |
|
||||||
if(stderr_fd) CloseHandle(g_hChildStd_ERR_Wr); |
|
||||||
} |
|
||||||
|
|
||||||
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; |
|
||||||
|
|
||||||
closed=false; |
|
||||||
data.id=process_info.dwProcessId; |
|
||||||
data.handle=process_info.hProcess; |
|
||||||
return process_info.dwProcessId; |
|
||||||
} |
|
||||||
|
|
||||||
void Process::async_read() { |
|
||||||
if(data.id==0) |
|
||||||
return; |
|
||||||
if(stdout_fd) { |
|
||||||
stdout_thread=std::thread([this](){ |
|
||||||
DWORD n; |
|
||||||
char buffer[buffer_size]; |
|
||||||
for (;;) { |
|
||||||
BOOL bSuccess = ReadFile(*stdout_fd, static_cast<CHAR*>(buffer), static_cast<DWORD>(buffer_size), &n, NULL); |
|
||||||
if(!bSuccess || n == 0) |
|
||||||
break; |
|
||||||
read_stdout(buffer, static_cast<size_t>(n)); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
if(stderr_fd) { |
|
||||||
stderr_thread=std::thread([this](){ |
|
||||||
DWORD n; |
|
||||||
char buffer[buffer_size]; |
|
||||||
for (;;) { |
|
||||||
BOOL bSuccess = ReadFile(*stderr_fd, static_cast<CHAR*>(buffer), static_cast<DWORD>(buffer_size), &n, NULL); |
|
||||||
if(!bSuccess || n == 0) |
|
||||||
break; |
|
||||||
read_stderr(buffer, static_cast<size_t>(n)); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
int Process::get_exit_status() { |
|
||||||
if(data.id==0) |
|
||||||
return -1; |
|
||||||
DWORD exit_status; |
|
||||||
WaitForSingleObject(data.handle, INFINITE); |
|
||||||
if(!GetExitCodeProcess(data.handle, &exit_status)) |
|
||||||
exit_status=-1; |
|
||||||
close_mutex.lock(); |
|
||||||
CloseHandle(data.handle); |
|
||||||
closed=true; |
|
||||||
close_mutex.unlock(); |
|
||||||
|
|
||||||
close_fds(); |
|
||||||
|
|
||||||
return static_cast<int>(exit_status); |
|
||||||
} |
|
||||||
|
|
||||||
void Process::close_fds() { |
|
||||||
if(stdout_thread.joinable()) |
|
||||||
stdout_thread.join(); |
|
||||||
if(stderr_thread.joinable()) |
|
||||||
stderr_thread.join(); |
|
||||||
|
|
||||||
if(stdin_fd) |
|
||||||
close_stdin(); |
|
||||||
if(stdout_fd) { |
|
||||||
CloseHandle(*stdout_fd); |
|
||||||
stdout_fd.reset(); |
|
||||||
} |
|
||||||
if(stderr_fd) { |
|
||||||
CloseHandle(*stderr_fd); |
|
||||||
stderr_fd.reset(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
bool Process::write(const char *bytes, size_t n) { |
|
||||||
stdin_mutex.lock(); |
|
||||||
if(stdin_fd) { |
|
||||||
DWORD written; |
|
||||||
BOOL bSuccess=WriteFile(*stdin_fd, bytes, static_cast<DWORD>(n), &written, NULL); |
|
||||||
if(!bSuccess || written==0) { |
|
||||||
stdin_mutex.unlock(); |
|
||||||
return false; |
|
||||||
} |
|
||||||
else { |
|
||||||
stdin_mutex.unlock(); |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
stdin_mutex.unlock(); |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
void Process::close_stdin() { |
|
||||||
stdin_mutex.lock(); |
|
||||||
if(stdin_fd) { |
|
||||||
CloseHandle(*stdin_fd); |
|
||||||
stdin_fd.reset(); |
|
||||||
} |
|
||||||
stdin_mutex.unlock(); |
|
||||||
} |
|
||||||
|
|
||||||
//Based on http://stackoverflow.com/a/1173396
|
|
||||||
void Process::kill(bool force) { |
|
||||||
close_mutex.lock(); |
|
||||||
if(data.id>0 && !closed) { |
|
||||||
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==data.id) { |
|
||||||
HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID); |
|
||||||
if(process_handle) TerminateProcess(process_handle, 2); |
|
||||||
} |
|
||||||
} while (Process32Next(snapshot, &process)); |
|
||||||
} |
|
||||||
} |
|
||||||
TerminateProcess(data.handle, 2); |
|
||||||
} |
|
||||||
close_mutex.unlock(); |
|
||||||
} |
|
||||||
|
|
||||||
//Based on http://stackoverflow.com/a/1173396
|
|
||||||
void Process::kill(id_type id, bool force) { |
|
||||||
if(id==0) |
|
||||||
return; |
|
||||||
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_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID); |
|
||||||
if(process_handle) TerminateProcess(process_handle, 2); |
|
||||||
} |
|
||||||
} while (Process32Next(snapshot, &process)); |
|
||||||
} |
|
||||||
} |
|
||||||
HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id); |
|
||||||
if(process_handle) TerminateProcess(process_handle, 2); |
|
||||||
} |
|
||||||
Loading…
Reference in new issue