mirror of
https://github.com/pocoproject/poco.git
synced 2025-04-16 23:12:57 +02:00
Merge pull request #1115 from mikedld/issue-1097-process-isrunning
Allow for process termination when polling with isRunning
This commit is contained in:
commit
f2d10a1351
@ -21,6 +21,9 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Poco/Foundation.h"
|
#include "Poco/Foundation.h"
|
||||||
|
#include "Poco/Event.h"
|
||||||
|
#include "Poco/Mutex.h"
|
||||||
|
#include "Poco/Optional.h"
|
||||||
#include "Poco/RefCountedObject.h"
|
#include "Poco/RefCountedObject.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -41,9 +44,13 @@ public:
|
|||||||
|
|
||||||
pid_t id() const;
|
pid_t id() const;
|
||||||
int wait() const;
|
int wait() const;
|
||||||
|
int wait(int options) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pid_t _pid;
|
const pid_t _pid;
|
||||||
|
mutable FastMutex _mutex;
|
||||||
|
mutable Event _event;
|
||||||
|
mutable Optional<int> _status;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "Poco/Exception.h"
|
#include "Poco/Exception.h"
|
||||||
#include "Poco/NumberFormatter.h"
|
#include "Poco/NumberFormatter.h"
|
||||||
#include "Poco/Pipe.h"
|
#include "Poco/Pipe.h"
|
||||||
|
#include "Poco/Thread.h"
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@ -42,7 +43,10 @@ namespace Poco {
|
|||||||
// ProcessHandleImpl
|
// ProcessHandleImpl
|
||||||
//
|
//
|
||||||
ProcessHandleImpl::ProcessHandleImpl(pid_t pid):
|
ProcessHandleImpl::ProcessHandleImpl(pid_t pid):
|
||||||
_pid(pid)
|
_pid(pid),
|
||||||
|
_mutex(),
|
||||||
|
_event(Event::EVENT_MANUALRESET),
|
||||||
|
_status()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,24 +64,60 @@ pid_t ProcessHandleImpl::id() const
|
|||||||
|
|
||||||
int ProcessHandleImpl::wait() const
|
int ProcessHandleImpl::wait() const
|
||||||
{
|
{
|
||||||
int status;
|
if (wait(0) != _pid)
|
||||||
int rc;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
rc = waitpid(_pid, &status, 0);
|
|
||||||
}
|
|
||||||
while (rc < 0 && errno == EINTR);
|
|
||||||
if (rc != _pid)
|
|
||||||
throw SystemException("Cannot wait for process", NumberFormatter::format(_pid));
|
throw SystemException("Cannot wait for process", NumberFormatter::format(_pid));
|
||||||
|
|
||||||
|
const int status = _status.value();
|
||||||
if (WIFEXITED(status))
|
if (WIFEXITED(status))
|
||||||
return WEXITSTATUS(status);
|
return WEXITSTATUS(status);
|
||||||
if (WIFSIGNALED(status))
|
if (WIFSIGNALED(status))
|
||||||
return -WTERMSIG(status);
|
return -WTERMSIG(status);
|
||||||
|
|
||||||
// This line should never be reached.
|
// This line should never be reached.
|
||||||
return std::numeric_limits<int>::max();
|
return std::numeric_limits<int>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ProcessHandleImpl::wait(int options) const
|
||||||
|
{
|
||||||
|
{
|
||||||
|
FastMutex::ScopedLock lock(_mutex);
|
||||||
|
if (_status.isSpecified())
|
||||||
|
{
|
||||||
|
return _pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int status;
|
||||||
|
int rc;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
rc = waitpid(_pid, &status, options);
|
||||||
|
}
|
||||||
|
while (rc < 0 && errno == EINTR);
|
||||||
|
|
||||||
|
if (rc == _pid)
|
||||||
|
{
|
||||||
|
FastMutex::ScopedLock lock(_mutex);
|
||||||
|
_status = status;
|
||||||
|
_event.set();
|
||||||
|
}
|
||||||
|
else if (rc < 0 && errno == ECHILD)
|
||||||
|
{
|
||||||
|
// Looks like another thread was lucky and it should update the status for us shortly
|
||||||
|
_event.wait();
|
||||||
|
|
||||||
|
FastMutex::ScopedLock lock(_mutex);
|
||||||
|
if (_status.isSpecified())
|
||||||
|
{
|
||||||
|
rc = _pid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// ProcessImpl
|
// ProcessImpl
|
||||||
//
|
//
|
||||||
@ -251,7 +291,7 @@ void ProcessImpl::killImpl(PIDImpl pid)
|
|||||||
|
|
||||||
bool ProcessImpl::isRunningImpl(const ProcessHandleImpl& handle)
|
bool ProcessImpl::isRunningImpl(const ProcessHandleImpl& handle)
|
||||||
{
|
{
|
||||||
return isRunningImpl(handle.id());
|
return handle.wait(WNOHANG) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "Poco/Process.h"
|
#include "Poco/Process.h"
|
||||||
#include "Poco/Pipe.h"
|
#include "Poco/Pipe.h"
|
||||||
#include "Poco/PipeStream.h"
|
#include "Poco/PipeStream.h"
|
||||||
|
#include "Poco/Thread.h"
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
|
||||||
|
|
||||||
@ -176,6 +177,27 @@ void ProcessTest::testIsRunning()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ProcessTest::testIsRunningAllowsForTermination()
|
||||||
|
{
|
||||||
|
#if !defined(_WIN32_WCE)
|
||||||
|
std::string name("TestApp");
|
||||||
|
std::string cmd;
|
||||||
|
|
||||||
|
#if defined(POCO_OS_FAMILY_UNIX)
|
||||||
|
cmd = "./";
|
||||||
|
cmd += name;
|
||||||
|
#else
|
||||||
|
cmd = name;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::vector<std::string> args;
|
||||||
|
ProcessHandle ph = Process::launch(cmd, args, 0, 0, 0);
|
||||||
|
while (Process::isRunning(ph))
|
||||||
|
Poco::Thread::sleep(100);
|
||||||
|
#endif // !defined(_WIN32_WCE)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ProcessTest::testSignalExitCode()
|
void ProcessTest::testSignalExitCode()
|
||||||
{
|
{
|
||||||
#if defined(POCO_OS_FAMILY_UNIX)
|
#if defined(POCO_OS_FAMILY_UNIX)
|
||||||
@ -213,6 +235,7 @@ CppUnit::Test* ProcessTest::suite()
|
|||||||
CppUnit_addTest(pSuite, ProcessTest, testLaunchRedirectOut);
|
CppUnit_addTest(pSuite, ProcessTest, testLaunchRedirectOut);
|
||||||
CppUnit_addTest(pSuite, ProcessTest, testLaunchEnv);
|
CppUnit_addTest(pSuite, ProcessTest, testLaunchEnv);
|
||||||
CppUnit_addTest(pSuite, ProcessTest, testIsRunning);
|
CppUnit_addTest(pSuite, ProcessTest, testIsRunning);
|
||||||
|
CppUnit_addTest(pSuite, ProcessTest, testIsRunningAllowsForTermination);
|
||||||
CppUnit_addTest(pSuite, ProcessTest, testSignalExitCode);
|
CppUnit_addTest(pSuite, ProcessTest, testSignalExitCode);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
|
@ -31,6 +31,7 @@ public:
|
|||||||
void testLaunchRedirectOut();
|
void testLaunchRedirectOut();
|
||||||
void testLaunchEnv();
|
void testLaunchEnv();
|
||||||
void testIsRunning();
|
void testIsRunning();
|
||||||
|
void testIsRunningAllowsForTermination();
|
||||||
void testSignalExitCode();
|
void testSignalExitCode();
|
||||||
|
|
||||||
void setUp();
|
void setUp();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user