mirror of
https://github.com/pocoproject/poco.git
synced 2025-03-04 07:27:23 +01:00
feat(Process): Process::isRunning returns true for defunct tagged process #1097 (WiP)
This commit is contained in:
parent
e2576ff5ab
commit
55476f6327
@ -19,11 +19,14 @@
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
#include "Poco/Event.h"
|
||||
#include "Poco/Mutex.h"
|
||||
#include "Poco/RefCountedObject.h"
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <atomic>
|
||||
#include <optional>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@ -40,10 +43,13 @@ public:
|
||||
|
||||
pid_t id() const;
|
||||
int wait() const;
|
||||
int wait(int options) const;
|
||||
int tryWait() const;
|
||||
|
||||
private:
|
||||
std::atomic<pid_t> _pid;
|
||||
const std::atomic<pid_t> _pid;
|
||||
mutable Event _event;
|
||||
mutable std::optional<std::atomic<int>> _status;
|
||||
};
|
||||
|
||||
|
||||
|
@ -40,7 +40,8 @@ namespace Poco {
|
||||
// ProcessHandleImpl
|
||||
//
|
||||
ProcessHandleImpl::ProcessHandleImpl(pid_t pid):
|
||||
_pid(pid)
|
||||
_pid(pid),
|
||||
_event(Event::EVENT_MANUALRESET)
|
||||
{
|
||||
}
|
||||
|
||||
@ -58,20 +59,40 @@ pid_t ProcessHandleImpl::id() const
|
||||
|
||||
int ProcessHandleImpl::wait() const
|
||||
{
|
||||
if (wait(0) != _pid)
|
||||
throw SystemException("Cannot wait for process", NumberFormatter::format(_pid));
|
||||
|
||||
return WEXITSTATUS(_status.value());
|
||||
}
|
||||
|
||||
|
||||
int ProcessHandleImpl::wait(int options) const
|
||||
{
|
||||
if (_status.has_value()) return _pid;
|
||||
int status;
|
||||
int rc;
|
||||
do
|
||||
{
|
||||
rc = waitpid(_pid, &status, 0);
|
||||
rc = waitpid(_pid, &status, options);
|
||||
}
|
||||
while (rc < 0 && errno == EINTR);
|
||||
if (rc != _pid)
|
||||
throw SystemException("Cannot wait for process", NumberFormatter::format(_pid));
|
||||
if (rc == _pid)
|
||||
{
|
||||
_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();
|
||||
|
||||
if (WIFEXITED(status)) // normal termination
|
||||
return WEXITSTATUS(status);
|
||||
else // termination by a signal
|
||||
return 256 + WTERMSIG(status);
|
||||
if (_status.has_value())
|
||||
{
|
||||
rc = _pid;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "Poco/PipeStream.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/Format.h"
|
||||
#include "Poco/Thread.h"
|
||||
|
||||
|
||||
using namespace std::string_literals;
|
||||
@ -25,6 +26,7 @@ using Poco::Pipe;
|
||||
using Poco::Path;
|
||||
using Poco::PipeInputStream;
|
||||
using Poco::PipeOutputStream;
|
||||
using Poco::Thread;
|
||||
|
||||
|
||||
ProcessTest::ProcessTest(const std::string& name): CppUnit::TestCase(name)
|
||||
@ -283,6 +285,45 @@ 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))
|
||||
Thread::sleep(100);
|
||||
#endif // !defined(_WIN32_WCE)
|
||||
}
|
||||
|
||||
|
||||
void ProcessTest::testSignalExitCode()
|
||||
{
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
std::string name("TestApp");
|
||||
std::string cmd;
|
||||
|
||||
cmd = "./";
|
||||
cmd += name;
|
||||
|
||||
std::vector<std::string> args;
|
||||
args.push_back("-raise-int");
|
||||
ProcessHandle ph = Process::launch(cmd, args, 0, 0, 0);
|
||||
int rc = ph.wait();
|
||||
assertEqual (-SIGINT, rc);
|
||||
#endif // defined(POCO_OS_FAMILY_UNIX)
|
||||
}
|
||||
|
||||
|
||||
void ProcessTest::setUp()
|
||||
{
|
||||
}
|
||||
@ -305,6 +346,8 @@ CppUnit::Test* ProcessTest::suite()
|
||||
CppUnit_addTest(pSuite, ProcessTest, testLaunchArgs);
|
||||
CppUnit_addTest(pSuite, ProcessTest, testLaunchInvalidCommand);
|
||||
CppUnit_addTest(pSuite, ProcessTest, testIsRunning);
|
||||
CppUnit_addTest(pSuite, ProcessTest, testIsRunningAllowsForTermination);
|
||||
CppUnit_addTest(pSuite, ProcessTest, testSignalExitCode);
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -32,6 +32,8 @@ public:
|
||||
void testLaunchArgs();
|
||||
void testLaunchInvalidCommand();
|
||||
void testIsRunning();
|
||||
void testIsRunningAllowsForTermination();
|
||||
void testSignalExitCode();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
Loading…
x
Reference in New Issue
Block a user