Browse Source

Some cleanups to process*

merge-requests/365/head
eidheim 10 years ago
parent
commit
29f2cc2f55
  1. 2
      src/process.cc
  2. 26
      src/process.h
  3. 16
      src/process_unix.cc
  4. 53
      src/process_win.cc

2
src/process.cc

@ -9,7 +9,7 @@ Process::Process(const std::string &command, const std::string &path,
bool open_stdin, size_t buffer_size): bool open_stdin, size_t buffer_size):
read_stdout(read_stdout), read_stderr(read_stderr), open_stdin(open_stdin), buffer_size(buffer_size) { read_stdout(read_stdout), read_stderr(read_stderr), open_stdin(open_stdin), buffer_size(buffer_size) {
id=open(command, path); id=open(command, path);
if(id!=0) if(id>0)
async_read(); async_read();
} }

26
src/process.h

@ -8,16 +8,24 @@
#include <thread> #include <thread>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
typedef DWORD process_id_type;
typedef HANDLE file_descriptor_type;
#else #else
#include <sys/wait.h> #include <sys/wait.h>
typedef pid_t process_id_type;
typedef int file_descriptor_type;
#endif #endif
///Create a new process given command and run path.
///Note: on Windows it seems impossible to specify which pipes to use.
///Thus, if read_stdout=nullptr, read_stderr=nullptr and open_std=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 { class Process {
public: 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
Process(const std::string &command, const std::string &path=std::string(), 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_stdout=nullptr,
std::function<void(const char *bytes, size_t n)> read_stderr=nullptr, std::function<void(const char *bytes, size_t n)> read_stderr=nullptr,
@ -26,7 +34,7 @@ public:
~Process(); ~Process();
///Get the process id of the started process. ///Get the process id of the started process.
process_id_type get_id() {return id;} id_type get_id() {return id;}
///Wait until process is finished, and return exit_code. ///Wait until process is finished, and return exit_code.
int get_exit_code(); int get_exit_code();
///Write to stdin. ///Write to stdin.
@ -35,7 +43,7 @@ public:
void close_stdin(); void close_stdin();
///Kill a given process id. ///Kill a given process id.
static void kill(process_id_type id, bool force=false); static void kill(id_type id, bool force=false);
private: private:
std::function<void(const char* bytes, size_t n)> read_stdout; std::function<void(const char* bytes, size_t n)> read_stdout;
@ -45,10 +53,10 @@ private:
std::mutex stdin_mutex; std::mutex stdin_mutex;
const size_t buffer_size; const size_t buffer_size;
std::unique_ptr<file_descriptor_type> stdout_fd, stderr_fd, stdin_fd; std::unique_ptr<fd_type> stdout_fd, stderr_fd, stdin_fd;
process_id_type open(const std::string &command, const std::string &path); id_type open(const std::string &command, const std::string &path);
process_id_type id; id_type id;
void async_read(); void async_read();
}; };

16
src/process_unix.cc

@ -6,13 +6,13 @@
#include <iostream> //TODO: remove #include <iostream> //TODO: remove
using namespace std; //TODO: remove using namespace std; //TODO: remove
process_id_type Process::open(const std::string &command, const std::string &path) { Process::id_type Process::open(const std::string &command, const std::string &path) {
if(open_stdin) if(open_stdin)
stdin_fd=std::unique_ptr<file_descriptor_type>(new file_descriptor_type); stdin_fd=std::unique_ptr<fd_type>(new fd_type);
if(read_stdout) if(read_stdout)
stdout_fd=std::unique_ptr<file_descriptor_type>(new file_descriptor_type); stdout_fd=std::unique_ptr<fd_type>(new fd_type);
if(read_stderr) if(read_stderr)
stderr_fd=std::unique_ptr<file_descriptor_type>(new file_descriptor_type); stderr_fd=std::unique_ptr<fd_type>(new fd_type);
int stdin_p[2], stdout_p[2], stderr_p[2]; int stdin_p[2], stdout_p[2], stderr_p[2];
@ -38,7 +38,7 @@ process_id_type Process::open(const std::string &command, const std::string &pat
return -1; return -1;
} }
process_id_type pid = fork(); id_type pid = fork();
if (pid < 0) { if (pid < 0) {
if(stdin_fd) close(stdin_p[0]); if(stdin_fd) close(stdin_p[0]);
@ -101,6 +101,8 @@ void Process::async_read() {
} }
int Process::get_exit_code() { int Process::get_exit_code() {
if(id<=0)
return -1;
int exit_code; int exit_code;
waitpid(id, &exit_code, 0); waitpid(id, &exit_code, 0);
@ -147,7 +149,9 @@ void Process::close_stdin() {
stdin_mutex.unlock(); stdin_mutex.unlock();
} }
void Process::kill(process_id_type id, bool force) { void Process::kill(id_type id, bool force) {
if(id<=0)
return;
if(force) if(force)
::kill(-id, SIGTERM); ::kill(-id, SIGTERM);
else else

53
src/process_win.cc

@ -5,16 +5,16 @@
#include <iostream> //TODO: remove #include <iostream> //TODO: remove
using namespace std; //TODO: remove using namespace std; //TODO: remove
//Based on the example at https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx //Based on the example at https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499(v=vs.85).aspx.
//Note: on Windows it seems impossible to specify which pipes to use //Note: on Windows it seems impossible to specify which pipes to use.
//Thus, if stdin_h, stdout_h and stderr all are NULL, the out,err,in is sent to the parent process instead //Thus, if read_stdout=nullptr, read_stderr=nullptr and open_std=false, the stdout, stderr and stdin are sent to the parent process instead.
process_id_type Process::open(const std::string &command, const std::string &path) { Process::id_type Process::open(const std::string &command, const std::string &path) {
if(open_stdin) if(open_stdin)
stdin_fd=std::unique_ptr<file_descriptor_type>(new file_descriptor_type); stdin_fd=std::unique_ptr<fd_type>(new fd_type);
if(read_stdout) if(read_stdout)
stdout_fd=std::unique_ptr<file_descriptor_type>(new file_descriptor_type); stdout_fd=std::unique_ptr<fd_type>(new fd_type);
if(read_stderr) if(read_stderr)
stderr_fd=std::unique_ptr<file_descriptor_type>(new file_descriptor_type); stderr_fd=std::unique_ptr<fd_type>(new fd_type);
HANDLE g_hChildStd_IN_Rd = NULL; HANDLE g_hChildStd_IN_Rd = NULL;
HANDLE g_hChildStd_IN_Wr = NULL; HANDLE g_hChildStd_IN_Wr = NULL;
@ -112,16 +112,8 @@ process_id_type Process::open(const std::string &command, const std::string &pat
std::strcpy(command_cstr, command.c_str()); std::strcpy(command_cstr, command.c_str());
#endif #endif
BOOL bSuccess = CreateProcess(NULL, BOOL bSuccess = CreateProcess(NULL, command_cstr, NULL, NULL, TRUE, 0,
command_cstr, // command line NULL, path_ptr, &siStartInfo, &process_info);
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
path_ptr, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&process_info); // receives PROCESS_INFORMATION
if(!bSuccess) { if(!bSuccess) {
CloseHandle(process_info.hProcess); CloseHandle(process_info.hProcess);
@ -173,11 +165,17 @@ void Process::async_read() {
} }
int Process::get_exit_code() { int Process::get_exit_code() {
if(id==0)
return -1;
DWORD exit_code; DWORD exit_code;
HANDLE process_info = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id); HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
WaitForSingleObject(process_info, INFINITE); if(process_handle) {
GetExitCodeProcess(process_info, &exit_code); WaitForSingleObject(process_handle, INFINITE);
CloseHandle(process_info); GetExitCodeProcess(process_handle, &exit_code);
CloseHandle(process_handle);
}
else
exit_code=-1;
if(stdout_thread.joinable()) if(stdout_thread.joinable())
stdout_thread.join(); stdout_thread.join();
@ -224,7 +222,10 @@ void Process::close_stdin() {
stdin_mutex.unlock(); stdin_mutex.unlock();
} }
void Process::kill(process_id_type id, bool force) { //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); HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(snapshot) { if(snapshot) {
PROCESSENTRY32 process; PROCESSENTRY32 process;
@ -233,12 +234,12 @@ void Process::kill(process_id_type id, bool force) {
if(Process32First(snapshot, &process)) { if(Process32First(snapshot, &process)) {
do { do {
if(process.th32ParentProcessID==id) { if(process.th32ParentProcessID==id) {
HANDLE process_info = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID); HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID);
if(process_info) TerminateProcess(process_info, 2); if(process_handle) TerminateProcess(process_handle, 2);
} }
} while (Process32Next(snapshot, &process)); } while (Process32Next(snapshot, &process));
} }
} }
HANDLE process_info = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id); HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
if(process_info) TerminateProcess(process_info, 2); if(process_handle) TerminateProcess(process_handle, 2);
} }

Loading…
Cancel
Save