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):
read_stdout(read_stdout), read_stderr(read_stderr), open_stdin(open_stdin), buffer_size(buffer_size) {
id=open(command, path);
if(id!=0)
if(id>0)
async_read();
}

26
src/process.h

@ -8,16 +8,24 @@
#include <thread>
#ifdef _WIN32
#include <windows.h>
typedef DWORD process_id_type;
typedef HANDLE file_descriptor_type;
#else
#include <sys/wait.h>
typedef pid_t process_id_type;
typedef int file_descriptor_type;
#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 {
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(),
std::function<void(const char *bytes, size_t n)> read_stdout=nullptr,
std::function<void(const char *bytes, size_t n)> read_stderr=nullptr,
@ -26,7 +34,7 @@ public:
~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.
int get_exit_code();
///Write to stdin.
@ -35,7 +43,7 @@ public:
void close_stdin();
///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:
std::function<void(const char* bytes, size_t n)> read_stdout;
@ -45,10 +53,10 @@ private:
std::mutex stdin_mutex;
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);
process_id_type id;
id_type open(const std::string &command, const std::string &path);
id_type id;
void async_read();
};

16
src/process_unix.cc

@ -6,13 +6,13 @@
#include <iostream> //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)
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)
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)
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];
@ -38,7 +38,7 @@ process_id_type Process::open(const std::string &command, const std::string &pat
return -1;
}
process_id_type pid = fork();
id_type pid = fork();
if (pid < 0) {
if(stdin_fd) close(stdin_p[0]);
@ -101,6 +101,8 @@ void Process::async_read() {
}
int Process::get_exit_code() {
if(id<=0)
return -1;
int exit_code;
waitpid(id, &exit_code, 0);
@ -147,7 +149,9 @@ void Process::close_stdin() {
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)
::kill(-id, SIGTERM);
else

53
src/process_win.cc

@ -5,16 +5,16 @@
#include <iostream> //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
//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
process_id_type Process::open(const std::string &command, const std::string &path) {
//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.
//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) {
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)
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)
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_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());
#endif
BOOL bSuccess = CreateProcess(NULL,
command_cstr, // command line
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
BOOL bSuccess = CreateProcess(NULL, command_cstr, NULL, NULL, TRUE, 0,
NULL, path_ptr, &siStartInfo, &process_info);
if(!bSuccess) {
CloseHandle(process_info.hProcess);
@ -173,11 +165,17 @@ void Process::async_read() {
}
int Process::get_exit_code() {
if(id==0)
return -1;
DWORD exit_code;
HANDLE process_info = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
WaitForSingleObject(process_info, INFINITE);
GetExitCodeProcess(process_info, &exit_code);
CloseHandle(process_info);
HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
if(process_handle) {
WaitForSingleObject(process_handle, INFINITE);
GetExitCodeProcess(process_handle, &exit_code);
CloseHandle(process_handle);
}
else
exit_code=-1;
if(stdout_thread.joinable())
stdout_thread.join();
@ -224,7 +222,10 @@ void Process::close_stdin() {
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);
if(snapshot) {
PROCESSENTRY32 process;
@ -233,12 +234,12 @@ void Process::kill(process_id_type id, bool force) {
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);
HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process.th32ProcessID);
if(process_handle) TerminateProcess(process_handle, 2);
}
} while (Process32Next(snapshot, &process));
}
}
HANDLE process_info = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
if(process_info) TerminateProcess(process_info, 2);
HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
if(process_handle) TerminateProcess(process_handle, 2);
}

Loading…
Cancel
Save