GH #2689: Added tryWait() into Process and ProcessHandle. Handle kill()-ed UNIX process exit codes.

This commit is contained in:
Günter Obiltschnig
2020-01-22 08:23:36 +01:00
parent 5f0e0a0374
commit 924cdf235c
12 changed files with 187 additions and 95 deletions

View File

@@ -21,7 +21,7 @@
#include "Poco/Foundation.h" #include "Poco/Foundation.h"
#if defined(POCO_OS_FAMILY_WINDOWS) #if defined(POCO_OS_FAMILY_WINDOWS)
#if defined(_WIN32_WCE) #if defined(_WIN32_WCE)
#include "Process_WINCE.h" #include "Process_WINCE.h"
#else #else
@@ -66,6 +66,11 @@ public:
/// Waits for the process to terminate /// Waits for the process to terminate
/// and returns the exit code of the process. /// and returns the exit code of the process.
int tryWait() const;
/// Checks that process is terminated
/// and returns the exit code of the process.
/// If the process is still running, returns -1.
protected: protected:
ProcessHandle(ProcessHandleImpl* pImpl); ProcessHandle(ProcessHandleImpl* pImpl);
@@ -211,6 +216,10 @@ public:
/// Waits for the process specified by handle to terminate /// Waits for the process specified by handle to terminate
/// and returns the exit code of the process. /// and returns the exit code of the process.
static int tryWait(const ProcessHandle& handle);
/// Checks that process is finished and returns the exit code of the
/// process. If the process is still running, returns -1.
static bool isRunning(const ProcessHandle& handle); static bool isRunning(const ProcessHandle& handle);
/// check if the process specified by handle is running or not /// check if the process specified by handle is running or not
/// ///

View File

@@ -36,10 +36,11 @@ class Foundation_API ProcessHandleImpl: public RefCountedObject
public: public:
ProcessHandleImpl(pid_t pid); ProcessHandleImpl(pid_t pid);
~ProcessHandleImpl(); ~ProcessHandleImpl();
pid_t id() const; pid_t id() const;
int wait() const; int wait() const;
int tryWait() const;
private: private:
pid_t _pid; pid_t _pid;
}; };
@@ -51,15 +52,15 @@ public:
typedef pid_t PIDImpl; typedef pid_t PIDImpl;
typedef std::vector<std::string> ArgsImpl; typedef std::vector<std::string> ArgsImpl;
typedef std::map<std::string, std::string> EnvImpl; typedef std::map<std::string, std::string> EnvImpl;
static PIDImpl idImpl(); static PIDImpl idImpl();
static void timesImpl(long& userTime, long& kernelTime); static void timesImpl(long& userTime, long& kernelTime);
static ProcessHandleImpl* launchImpl( static ProcessHandleImpl* launchImpl(
const std::string& command, const std::string& command,
const ArgsImpl& args, const ArgsImpl& args,
const std::string& initialDirectory, const std::string& initialDirectory,
Pipe* inPipe, Pipe* inPipe,
Pipe* outPipe, Pipe* outPipe,
Pipe* errPipe, Pipe* errPipe,
const EnvImpl& env); const EnvImpl& env);
static void killImpl(ProcessHandleImpl& handle); static void killImpl(ProcessHandleImpl& handle);
@@ -70,11 +71,11 @@ public:
private: private:
static ProcessHandleImpl* launchByForkExecImpl( static ProcessHandleImpl* launchByForkExecImpl(
const std::string& command, const std::string& command,
const ArgsImpl& args, const ArgsImpl& args,
const std::string& initialDirectory, const std::string& initialDirectory,
Pipe* inPipe, Pipe* inPipe,
Pipe* outPipe, Pipe* outPipe,
Pipe* errPipe, Pipe* errPipe,
const EnvImpl& env); const EnvImpl& env);
}; };

View File

@@ -38,10 +38,11 @@ class Foundation_API ProcessHandleImpl: public RefCountedObject
public: public:
ProcessHandleImpl(int pid); ProcessHandleImpl(int pid);
~ProcessHandleImpl(); ~ProcessHandleImpl();
int id() const; int id() const;
int wait() const; int wait() const;
int tryWait() const;
private: private:
int _pid; int _pid;
}; };
@@ -53,15 +54,15 @@ public:
typedef int PIDImpl; typedef int PIDImpl;
typedef std::vector<std::string> ArgsImpl; typedef std::vector<std::string> ArgsImpl;
typedef std::map<std::string, std::string> EnvImpl; typedef std::map<std::string, std::string> EnvImpl;
static PIDImpl idImpl(); static PIDImpl idImpl();
static void timesImpl(long& userTime, long& kernelTime); static void timesImpl(long& userTime, long& kernelTime);
static ProcessHandleImpl* launchImpl( static ProcessHandleImpl* launchImpl(
const std::string& command, const std::string& command,
const ArgsImpl& args, const ArgsImpl& args,
const std::string& initialDirectory, const std::string& initialDirectory,
Pipe* inPipe, Pipe* inPipe,
Pipe* outPipe, Pipe* outPipe,
Pipe* errPipe, Pipe* errPipe,
const EnvImpl& env); const EnvImpl& env);
static void killImpl(ProcessHandleImpl& handle); static void killImpl(ProcessHandleImpl& handle);

View File

@@ -36,16 +36,17 @@ class Foundation_API ProcessHandleImpl: public RefCountedObject
public: public:
ProcessHandleImpl(HANDLE _hProcess, UInt32 pid); ProcessHandleImpl(HANDLE _hProcess, UInt32 pid);
~ProcessHandleImpl(); ~ProcessHandleImpl();
UInt32 id() const; UInt32 id() const;
HANDLE process() const; HANDLE process() const;
int wait() const; int wait() const;
int tryWait() const;
void closeHandle(); void closeHandle();
private: private:
HANDLE _hProcess; HANDLE _hProcess;
UInt32 _pid; UInt32 _pid;
ProcessHandleImpl(const ProcessHandleImpl&); ProcessHandleImpl(const ProcessHandleImpl&);
ProcessHandleImpl& operator = (const ProcessHandleImpl&); ProcessHandleImpl& operator = (const ProcessHandleImpl&);
}; };
@@ -57,15 +58,15 @@ public:
typedef UInt32 PIDImpl; typedef UInt32 PIDImpl;
typedef std::vector<std::string> ArgsImpl; typedef std::vector<std::string> ArgsImpl;
typedef std::map<std::string, std::string> EnvImpl; typedef std::map<std::string, std::string> EnvImpl;
static PIDImpl idImpl(); static PIDImpl idImpl();
static void timesImpl(long& userTime, long& kernelTime); static void timesImpl(long& userTime, long& kernelTime);
static ProcessHandleImpl* launchImpl( static ProcessHandleImpl* launchImpl(
const std::string& command, const std::string& command,
const ArgsImpl& args, const ArgsImpl& args,
const std::string& initialDirectory, const std::string& initialDirectory,
Pipe* inPipe, Pipe* inPipe,
Pipe* outPipe, Pipe* outPipe,
Pipe* errPipe, Pipe* errPipe,
const EnvImpl& env); const EnvImpl& env);
static void killImpl(ProcessHandleImpl& handle); static void killImpl(ProcessHandleImpl& handle);

View File

@@ -36,10 +36,11 @@ class Foundation_API ProcessHandleImpl: public RefCountedObject
public: public:
ProcessHandleImpl(HANDLE _hProcess, UInt32 pid); ProcessHandleImpl(HANDLE _hProcess, UInt32 pid);
~ProcessHandleImpl(); ~ProcessHandleImpl();
UInt32 id() const; UInt32 id() const;
HANDLE process() const; HANDLE process() const;
int wait() const; int wait() const;
int tryWait() const;
void closeHandle(); void closeHandle();
private: private:
@@ -57,15 +58,15 @@ public:
typedef UInt32 PIDImpl; typedef UInt32 PIDImpl;
typedef std::vector<std::string> ArgsImpl; typedef std::vector<std::string> ArgsImpl;
typedef std::map<std::string, std::string> EnvImpl; typedef std::map<std::string, std::string> EnvImpl;
static PIDImpl idImpl(); static PIDImpl idImpl();
static void timesImpl(long& userTime, long& kernelTime); static void timesImpl(long& userTime, long& kernelTime);
static ProcessHandleImpl* launchImpl( static ProcessHandleImpl* launchImpl(
const std::string& command, const std::string& command,
const ArgsImpl& args, const ArgsImpl& args,
const std::string& initialDirectory, const std::string& initialDirectory,
Pipe* inPipe, Pipe* inPipe,
Pipe* outPipe, Pipe* outPipe,
Pipe* errPipe, Pipe* errPipe,
const EnvImpl& env); const EnvImpl& env);
static void killImpl(ProcessHandleImpl& handle); static void killImpl(ProcessHandleImpl& handle);

View File

@@ -36,10 +36,11 @@ class Foundation_API ProcessHandleImpl: public RefCountedObject
public: public:
ProcessHandleImpl(HANDLE _hProcess, UInt32 pid); ProcessHandleImpl(HANDLE _hProcess, UInt32 pid);
~ProcessHandleImpl(); ~ProcessHandleImpl();
UInt32 id() const; UInt32 id() const;
HANDLE process() const; HANDLE process() const;
int wait() const; int wait() const;
int tryWait() const;
void closeHandle(); void closeHandle();
private: private:
@@ -57,15 +58,15 @@ public:
typedef UInt32 PIDImpl; typedef UInt32 PIDImpl;
typedef std::vector<std::string> ArgsImpl; typedef std::vector<std::string> ArgsImpl;
typedef std::map<std::string, std::string> EnvImpl; typedef std::map<std::string, std::string> EnvImpl;
static PIDImpl idImpl(); static PIDImpl idImpl();
static void timesImpl(long& userTime, long& kernelTime); static void timesImpl(long& userTime, long& kernelTime);
static ProcessHandleImpl* launchImpl( static ProcessHandleImpl* launchImpl(
const std::string& command, const std::string& command,
const ArgsImpl& args, const ArgsImpl& args,
const std::string& initialDirectory, const std::string& initialDirectory,
Pipe* inPipe, Pipe* inPipe,
Pipe* outPipe, Pipe* outPipe,
Pipe* errPipe, Pipe* errPipe,
const EnvImpl& env); const EnvImpl& env);
static void killImpl(ProcessHandleImpl& handle); static void killImpl(ProcessHandleImpl& handle);

View File

@@ -110,6 +110,12 @@ int ProcessHandle::wait() const
} }
int ProcessHandle::tryWait() const
{
return _pImpl->tryWait();
}
// //
// Process // Process
// //
@@ -166,6 +172,12 @@ int Process::wait(const ProcessHandle& handle)
} }
int Process::tryWait(const ProcessHandle& handle)
{
return handle.tryWait();
}
void Process::kill(ProcessHandle& handle) void Process::kill(ProcessHandle& handle)
{ {
killImpl(*handle._pImpl); killImpl(*handle._pImpl);

View File

@@ -66,7 +66,31 @@ int ProcessHandleImpl::wait() const
while (rc < 0 && errno == EINTR); while (rc < 0 && errno == EINTR);
if (rc != _pid) if (rc != _pid)
throw SystemException("Cannot wait for process", NumberFormatter::format(_pid)); throw SystemException("Cannot wait for process", NumberFormatter::format(_pid));
return WEXITSTATUS(status);
if (WIFEXITED(status)) // normal termination
return WEXITSTATUS(status);
else // termination by a signal
return 256 + WTERMSIG(status);
}
int ProcessHandleImpl::tryWait() const
{
int status;
int rc;
do
{
rc = waitpid(_pid, &status, WNOHANG);
}
while (rc < 0 && errno == EINTR);
if (rc == 0)
return -1;
if (rc != _pid)
throw SystemException("Cannot wait for process", NumberFormatter::format(_pid));
if (WIFEXITED(status)) // normal termination
return WEXITSTATUS(status);
else // termination by a signal
return 256 + WTERMSIG(status);
} }
@@ -97,7 +121,7 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
char** argv = new char*[args.size() + 2]; char** argv = new char*[args.size() + 2];
int i = 0; int i = 0;
argv[i++] = const_cast<char*>(command.c_str()); argv[i++] = const_cast<char*>(command.c_str());
for (const auto& a: args) for (const auto& a: args)
argv[i++] = const_cast<char*>(a.c_str()); argv[i++] = const_cast<char*>(a.c_str());
argv[i] = NULL; argv[i] = NULL;
struct inheritance inherit; struct inheritance inherit;
@@ -107,7 +131,7 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
fdmap[0] = inPipe ? inPipe->readHandle() : 0; fdmap[0] = inPipe ? inPipe->readHandle() : 0;
fdmap[1] = outPipe ? outPipe->writeHandle() : 1; fdmap[1] = outPipe ? outPipe->writeHandle() : 1;
fdmap[2] = errPipe ? errPipe->writeHandle() : 2; fdmap[2] = errPipe ? errPipe->writeHandle() : 2;
char** envPtr = 0; char** envPtr = 0;
std::vector<char> envChars; std::vector<char> envChars;
std::vector<char*> envPtrs; std::vector<char*> envPtrs;
@@ -125,10 +149,10 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
envPtrs.push_back(0); envPtrs.push_back(0);
envPtr = &envPtrs[0]; envPtr = &envPtrs[0];
} }
int pid = spawn(command.c_str(), 3, fdmap, &inherit, argv, envPtr); int pid = spawn(command.c_str(), 3, fdmap, &inherit, argv, envPtr);
delete [] argv; delete [] argv;
if (pid == -1) if (pid == -1)
throw SystemException("cannot spawn", command); throw SystemException("cannot spawn", command);
if (inPipe) inPipe->close(Pipe::CLOSE_READ); if (inPipe) inPipe->close(Pipe::CLOSE_READ);
@@ -155,18 +179,18 @@ ProcessHandleImpl* ProcessImpl::launchByForkExecImpl(const std::string& command,
std::vector<char*> argv(args.size() + 2); std::vector<char*> argv(args.size() + 2);
int i = 0; int i = 0;
argv[i++] = const_cast<char*>(command.c_str()); argv[i++] = const_cast<char*>(command.c_str());
for (const auto& a: args) for (const auto& a: args)
{ {
argv[i++] = const_cast<char*>(a.c_str()); argv[i++] = const_cast<char*>(a.c_str());
} }
argv[i] = NULL; argv[i] = NULL;
const char* pInitialDirectory = initialDirectory.empty() ? 0 : initialDirectory.c_str(); const char* pInitialDirectory = initialDirectory.empty() ? 0 : initialDirectory.c_str();
int pid = fork(); int pid = fork();
if (pid < 0) if (pid < 0)
{ {
throw SystemException("Cannot fork process for", command); throw SystemException("Cannot fork process for", command);
} }
else if (pid == 0) else if (pid == 0)
{ {
@@ -247,19 +271,19 @@ bool ProcessImpl::isRunningImpl(const ProcessHandleImpl& handle)
} }
bool ProcessImpl::isRunningImpl(PIDImpl pid) bool ProcessImpl::isRunningImpl(PIDImpl pid)
{ {
if (kill(pid, 0) == 0) if (kill(pid, 0) == 0)
{ {
return true; return true;
} }
else else
{ {
return false; return false;
} }
} }
void ProcessImpl::requestTerminationImpl(PIDImpl pid) void ProcessImpl::requestTerminationImpl(PIDImpl pid)
{ {
if (kill(pid, SIGINT) != 0) if (kill(pid, SIGINT) != 0)

View File

@@ -45,6 +45,12 @@ int ProcessHandleImpl::wait() const
} }
int ProcessHandleImpl::tryWait() const
{
throw Poco::NotImplementedException("Process::tryWait()");
}
// //
// ProcessImpl // ProcessImpl
// //
@@ -79,13 +85,13 @@ void ProcessImpl::killImpl(PIDImpl pid)
} }
bool ProcessImpl::isRunningImpl(const ProcessHandleImpl& handle) bool ProcessImpl::isRunningImpl(const ProcessHandleImpl& handle)
{ {
throw Poco::NotImplementedException("Process::is_running()"); throw Poco::NotImplementedException("Process::is_running()");
} }
bool ProcessImpl::isRunningImpl(PIDImpl pid) bool ProcessImpl::isRunningImpl(PIDImpl pid)
{ {
throw Poco::NotImplementedException("Process::is_running()"); throw Poco::NotImplementedException("Process::is_running()");
} }

View File

@@ -74,6 +74,18 @@ int ProcessHandleImpl::wait() const
} }
int ProcessHandleImpl::tryWait() const
{
DWORD exitCode;
if (GetExitCodeProcess(_hProcess, &exitCode) == 0)
throw SystemException("Cannot get exit code for process", NumberFormatter::format(_pid));
if (exitCode == STILL_ACTIVE)
return -1;
else
return exitCode;
}
// //
// ProcessImpl // ProcessImpl
// //
@@ -99,7 +111,7 @@ void ProcessImpl::timesImpl(long& userTime, long& kernelTime)
time.LowPart = ftUser.dwLowDateTime; time.LowPart = ftUser.dwLowDateTime;
time.HighPart = ftUser.dwHighDateTime; time.HighPart = ftUser.dwHighDateTime;
userTime = long(time.QuadPart / 10000000L); userTime = long(time.QuadPart / 10000000L);
} }
else else
{ {
userTime = kernelTime = -1; userTime = kernelTime = -1;
@@ -137,12 +149,12 @@ static std::string escapeArg(const std::string& arg)
{ {
quotedArg.append(2 * backslashCount, '\\'); quotedArg.append(2 * backslashCount, '\\');
break; break;
} }
else if ('"' == *it) else if ('"' == *it)
{ {
quotedArg.append(2 * backslashCount + 1, '\\'); quotedArg.append(2 * backslashCount + 1, '\\');
quotedArg.push_back('"'); quotedArg.push_back('"');
} }
else else
{ {
quotedArg.append(backslashCount, '\\'); quotedArg.append(backslashCount, '\\');
@@ -151,7 +163,7 @@ static std::string escapeArg(const std::string& arg)
} }
quotedArg.push_back('"'); quotedArg.push_back('"');
return quotedArg; return quotedArg;
} }
else else
{ {
return arg; return arg;
@@ -185,12 +197,12 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
DuplicateHandle(hProc, inPipe->readHandle(), hProc, &startupInfo.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS); DuplicateHandle(hProc, inPipe->readHandle(), hProc, &startupInfo.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS);
mustInheritHandles = true; mustInheritHandles = true;
inPipe->close(Pipe::CLOSE_READ); inPipe->close(Pipe::CLOSE_READ);
} }
else if (GetStdHandle(STD_INPUT_HANDLE)) else if (GetStdHandle(STD_INPUT_HANDLE))
{ {
DuplicateHandle(hProc, GetStdHandle(STD_INPUT_HANDLE), hProc, &startupInfo.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS); DuplicateHandle(hProc, GetStdHandle(STD_INPUT_HANDLE), hProc, &startupInfo.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS);
mustInheritHandles = true; mustInheritHandles = true;
} }
else else
{ {
startupInfo.hStdInput = 0; startupInfo.hStdInput = 0;
@@ -200,12 +212,12 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
{ {
DuplicateHandle(hProc, outPipe->writeHandle(), hProc, &startupInfo.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS); DuplicateHandle(hProc, outPipe->writeHandle(), hProc, &startupInfo.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS);
mustInheritHandles = true; mustInheritHandles = true;
} }
else if (GetStdHandle(STD_OUTPUT_HANDLE)) else if (GetStdHandle(STD_OUTPUT_HANDLE))
{ {
DuplicateHandle(hProc, GetStdHandle(STD_OUTPUT_HANDLE), hProc, &startupInfo.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS); DuplicateHandle(hProc, GetStdHandle(STD_OUTPUT_HANDLE), hProc, &startupInfo.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS);
mustInheritHandles = true; mustInheritHandles = true;
} }
else else
{ {
startupInfo.hStdOutput = 0; startupInfo.hStdOutput = 0;
@@ -214,12 +226,12 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
{ {
DuplicateHandle(hProc, errPipe->writeHandle(), hProc, &startupInfo.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS); DuplicateHandle(hProc, errPipe->writeHandle(), hProc, &startupInfo.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS);
mustInheritHandles = true; mustInheritHandles = true;
} }
else if (GetStdHandle(STD_ERROR_HANDLE)) else if (GetStdHandle(STD_ERROR_HANDLE))
{ {
DuplicateHandle(hProc, GetStdHandle(STD_ERROR_HANDLE), hProc, &startupInfo.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS); DuplicateHandle(hProc, GetStdHandle(STD_ERROR_HANDLE), hProc, &startupInfo.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS);
mustInheritHandles = true; mustInheritHandles = true;
} }
else else
{ {
startupInfo.hStdError = 0; startupInfo.hStdError = 0;
@@ -263,7 +275,7 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
{ {
CloseHandle(processInfo.hThread); CloseHandle(processInfo.hThread);
return new ProcessHandleImpl(processInfo.hProcess, processInfo.dwProcessId); return new ProcessHandleImpl(processInfo.hProcess, processInfo.dwProcessId);
} }
else throw SystemException("Cannot launch process", command); else throw SystemException("Cannot launch process", command);
} }
@@ -292,14 +304,14 @@ void ProcessImpl::killImpl(PIDImpl pid)
throw SystemException("cannot kill process"); throw SystemException("cannot kill process");
} }
CloseHandle(hProc); CloseHandle(hProc);
} }
else else
{ {
switch (GetLastError()) switch (GetLastError())
{ {
case ERROR_ACCESS_DENIED: case ERROR_ACCESS_DENIED:
throw NoPermissionException("cannot kill process"); throw NoPermissionException("cannot kill process");
case ERROR_NOT_FOUND: case ERROR_NOT_FOUND:
throw NotFoundException("cannot kill process"); throw NotFoundException("cannot kill process");
case ERROR_INVALID_PARAMETER: case ERROR_INVALID_PARAMETER:
throw NotFoundException("cannot kill process"); throw NotFoundException("cannot kill process");

View File

@@ -78,6 +78,18 @@ int ProcessHandleImpl::wait() const
} }
int ProcessHandleImpl::tryWait() const
{
DWORD exitCode;
if (GetExitCodeProcess(_hProcess, &exitCode) == 0)
throw SystemException("Cannot get exit code for process", NumberFormatter::format(_pid));
if (exitCode == STILL_ACTIVE)
return -1;
else
return exitCode;
}
// //
// ProcessImpl // ProcessImpl
// //
@@ -103,7 +115,7 @@ void ProcessImpl::timesImpl(long& userTime, long& kernelTime)
time.LowPart = ftUser.dwLowDateTime; time.LowPart = ftUser.dwLowDateTime;
time.HighPart = ftUser.dwHighDateTime; time.HighPart = ftUser.dwHighDateTime;
userTime = long(time.QuadPart / 10000000L); userTime = long(time.QuadPart / 10000000L);
} }
else else
{ {
userTime = kernelTime = -1; userTime = kernelTime = -1;
@@ -141,12 +153,12 @@ static std::string escapeArg(const std::string& arg)
{ {
quotedArg.append(2 * backslashCount, '\\'); quotedArg.append(2 * backslashCount, '\\');
break; break;
} }
else if ('"' == *it) else if ('"' == *it)
{ {
quotedArg.append(2 * backslashCount + 1, '\\'); quotedArg.append(2 * backslashCount + 1, '\\');
quotedArg.push_back('"'); quotedArg.push_back('"');
} }
else else
{ {
quotedArg.append(backslashCount, '\\'); quotedArg.append(backslashCount, '\\');
@@ -155,7 +167,7 @@ static std::string escapeArg(const std::string& arg)
} }
quotedArg.push_back('"'); quotedArg.push_back('"');
return quotedArg; return quotedArg;
} }
else else
{ {
return arg; return arg;
@@ -205,12 +217,12 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
DuplicateHandle(hProc, inPipe->readHandle(), hProc, &startupInfo.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS); DuplicateHandle(hProc, inPipe->readHandle(), hProc, &startupInfo.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS);
mustInheritHandles = true; mustInheritHandles = true;
inPipe->close(Pipe::CLOSE_READ); inPipe->close(Pipe::CLOSE_READ);
} }
else if (GetStdHandle(STD_INPUT_HANDLE)) else if (GetStdHandle(STD_INPUT_HANDLE))
{ {
DuplicateHandle(hProc, GetStdHandle(STD_INPUT_HANDLE), hProc, &startupInfo.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS); DuplicateHandle(hProc, GetStdHandle(STD_INPUT_HANDLE), hProc, &startupInfo.hStdInput, 0, TRUE, DUPLICATE_SAME_ACCESS);
mustInheritHandles = true; mustInheritHandles = true;
} }
else else
{ {
startupInfo.hStdInput = 0; startupInfo.hStdInput = 0;
@@ -220,12 +232,12 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
{ {
DuplicateHandle(hProc, outPipe->writeHandle(), hProc, &startupInfo.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS); DuplicateHandle(hProc, outPipe->writeHandle(), hProc, &startupInfo.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS);
mustInheritHandles = true; mustInheritHandles = true;
} }
else if (GetStdHandle(STD_OUTPUT_HANDLE)) else if (GetStdHandle(STD_OUTPUT_HANDLE))
{ {
DuplicateHandle(hProc, GetStdHandle(STD_OUTPUT_HANDLE), hProc, &startupInfo.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS); DuplicateHandle(hProc, GetStdHandle(STD_OUTPUT_HANDLE), hProc, &startupInfo.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS);
mustInheritHandles = true; mustInheritHandles = true;
} }
else else
{ {
startupInfo.hStdOutput = 0; startupInfo.hStdOutput = 0;
@@ -234,12 +246,12 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
{ {
DuplicateHandle(hProc, errPipe->writeHandle(), hProc, &startupInfo.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS); DuplicateHandle(hProc, errPipe->writeHandle(), hProc, &startupInfo.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS);
mustInheritHandles = true; mustInheritHandles = true;
} }
else if (GetStdHandle(STD_ERROR_HANDLE)) else if (GetStdHandle(STD_ERROR_HANDLE))
{ {
DuplicateHandle(hProc, GetStdHandle(STD_ERROR_HANDLE), hProc, &startupInfo.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS); DuplicateHandle(hProc, GetStdHandle(STD_ERROR_HANDLE), hProc, &startupInfo.hStdError, 0, TRUE, DUPLICATE_SAME_ACCESS);
mustInheritHandles = true; mustInheritHandles = true;
} }
else else
{ {
startupInfo.hStdError = 0; startupInfo.hStdError = 0;
@@ -285,7 +297,7 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
{ {
CloseHandle(processInfo.hThread); CloseHandle(processInfo.hThread);
return new ProcessHandleImpl(processInfo.hProcess, processInfo.dwProcessId); return new ProcessHandleImpl(processInfo.hProcess, processInfo.dwProcessId);
} }
else throw SystemException("Cannot launch process", command); else throw SystemException("Cannot launch process", command);
} }
@@ -314,14 +326,14 @@ void ProcessImpl::killImpl(PIDImpl pid)
throw SystemException("cannot kill process"); throw SystemException("cannot kill process");
} }
CloseHandle(hProc); CloseHandle(hProc);
} }
else else
{ {
switch (GetLastError()) switch (GetLastError())
{ {
case ERROR_ACCESS_DENIED: case ERROR_ACCESS_DENIED:
throw NoPermissionException("cannot kill process"); throw NoPermissionException("cannot kill process");
case ERROR_NOT_FOUND: case ERROR_NOT_FOUND:
throw NotFoundException("cannot kill process"); throw NotFoundException("cannot kill process");
case ERROR_INVALID_PARAMETER: case ERROR_INVALID_PARAMETER:
throw NotFoundException("cannot kill process"); throw NotFoundException("cannot kill process");

View File

@@ -73,12 +73,24 @@ int ProcessHandleImpl::wait() const
} }
int ProcessHandleImpl::tryWait() const
{
DWORD exitCode;
if (GetExitCodeProcess(_hProcess, &exitCode) == 0)
throw SystemException("Cannot get exit code for process", NumberFormatter::format(_pid));
if (exitCode == STILL_ACTIVE)
return -1;
else
return exitCode;
}
// //
// ProcessImpl // ProcessImpl
// //
ProcessImpl::PIDImpl ProcessImpl::idImpl() ProcessImpl::PIDImpl ProcessImpl::idImpl()
{ {
return GetCurrentProcessId(); return GetCurrentProcessId();
} }
@@ -110,28 +122,28 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
{ {
std::wstring ucommand; std::wstring ucommand;
UnicodeConverter::toUTF16(command, ucommand); UnicodeConverter::toUTF16(command, ucommand);
std::string commandLine; std::string commandLine;
for (ArgsImpl::const_iterator it = args.begin(); it != args.end(); ++it) for (ArgsImpl::const_iterator it = args.begin(); it != args.end(); ++it)
{ {
if (it != args.begin()) commandLine.append(" "); if (it != args.begin()) commandLine.append(" ");
commandLine.append(*it); commandLine.append(*it);
} }
std::wstring ucommandLine; std::wstring ucommandLine;
UnicodeConverter::toUTF16(commandLine, ucommandLine); UnicodeConverter::toUTF16(commandLine, ucommandLine);
PROCESS_INFORMATION processInfo; PROCESS_INFORMATION processInfo;
BOOL rc = CreateProcessW( BOOL rc = CreateProcessW(
ucommand.c_str(), ucommand.c_str(),
const_cast<wchar_t*>(ucommandLine.c_str()), const_cast<wchar_t*>(ucommandLine.c_str()),
NULL, NULL,
NULL, NULL,
FALSE, FALSE,
0, 0,
NULL, NULL,
NULL, NULL,
NULL/*&startupInfo*/, NULL/*&startupInfo*/,
&processInfo &processInfo
); );
@@ -146,7 +158,7 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
void ProcessImpl::killImpl(ProcessHandleImpl& handle) void ProcessImpl::killImpl(ProcessHandleImpl& handle)
{ {
if (handle.process()) if (handle.process())
{ {
if (TerminateProcess(handle.process(), 0) == 0) if (TerminateProcess(handle.process(), 0) == 0)
{ {
@@ -176,7 +188,7 @@ void ProcessImpl::killImpl(PIDImpl pid)
{ {
case ERROR_ACCESS_DENIED: case ERROR_ACCESS_DENIED:
throw NoPermissionException("cannot kill process"); throw NoPermissionException("cannot kill process");
case ERROR_NOT_FOUND: case ERROR_NOT_FOUND:
throw NotFoundException("cannot kill process"); throw NotFoundException("cannot kill process");
default: default:
throw SystemException("cannot kill process"); throw SystemException("cannot kill process");
@@ -185,7 +197,7 @@ void ProcessImpl::killImpl(PIDImpl pid)
} }
bool ProcessImpl::isRunningImpl(const ProcessHandleImpl& handle) bool ProcessImpl::isRunningImpl(const ProcessHandleImpl& handle)
{ {
bool result = true; bool result = true;
DWORD exitCode; DWORD exitCode;
@@ -195,7 +207,7 @@ bool ProcessImpl::isRunningImpl(const ProcessHandleImpl& handle)
} }
bool ProcessImpl::isRunningImpl(PIDImpl pid) bool ProcessImpl::isRunningImpl(PIDImpl pid)
{ {
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
bool result = true; bool result = true;