feat(Process): Process::isRunning returns true for defunct tagged process #1097 (WiP)

This commit is contained in:
Alex Fabijanic 2024-12-07 17:27:32 -06:00
parent e2576ff5ab
commit 55476f6327
4 changed files with 81 additions and 9 deletions

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;
}

View File

@ -32,6 +32,8 @@ public:
void testLaunchArgs();
void testLaunchInvalidCommand();
void testIsRunning();
void testIsRunningAllowsForTermination();
void testSignalExitCode();
void setUp();
void tearDown();