mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-26 18:42:41 +01:00
GH #2689: Added tryWait() into Process and ProcessHandle. Handle kill()-ed UNIX process exit codes.
This commit is contained in:
@@ -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
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -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);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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()");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user