Skip to content

Commit

Permalink
fixed pocoproject#1097 cherry-pick of 0425866
Browse files Browse the repository at this point in the history
  • Loading branch information
mikedld authored and josh-stoddard-tanium committed Nov 8, 2018
1 parent ae9a736 commit dbeab4f
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 7 deletions.
9 changes: 8 additions & 1 deletion Foundation/include/Poco/Process_UNIX.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@


#include "Poco/Foundation.h"
#include "Poco/Event.h"
#include "Poco/Mutex.h"
#include "Poco/Optional.h"
#include "Poco/RefCountedObject.h"
#include <unistd.h>
#include <vector>
Expand All @@ -39,9 +42,13 @@ class Foundation_API ProcessHandleImpl: public RefCountedObject

pid_t id() const;
int wait() const;
int wait(int options) const;

private:
pid_t _pid;
const pid_t _pid;
mutable FastMutex _mutex;
mutable Event _event;
mutable Optional<int> _status;
};


Expand Down
52 changes: 46 additions & 6 deletions Foundation/src/Process_UNIX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include "Poco/Exception.h"
#include "Poco/NumberFormatter.h"
#include "Poco/Pipe.h"
#include "Poco/Thread.h"
#include <limits>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
Expand All @@ -39,7 +41,10 @@ namespace Poco {
// ProcessHandleImpl
//
ProcessHandleImpl::ProcessHandleImpl(pid_t pid):
_pid(pid)
_pid(pid),
_mutex(),
_event(Event::EVENT_MANUALRESET),
_status()
{
}

Expand All @@ -57,16 +62,51 @@ pid_t ProcessHandleImpl::id() const

int ProcessHandleImpl::wait() const
{
if (wait(0) != _pid)
throw SystemException("Cannot wait for process", NumberFormatter::format(_pid));

const int status = _status.value();
return WEXITSTATUS(status);
}


int ProcessHandleImpl::wait(int options) const
{
{
FastMutex::ScopedLock lock(_mutex);
if (_status.isSpecified())
{
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));
return WEXITSTATUS(status);

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


Expand Down Expand Up @@ -243,7 +283,7 @@ void ProcessImpl::killImpl(PIDImpl pid)

bool ProcessImpl::isRunningImpl(const ProcessHandleImpl& handle)
{
return isRunningImpl(handle.id());
return handle.wait(WNOHANG) == 0;
}


Expand Down
43 changes: 43 additions & 0 deletions Foundation/testsuite/src/ProcessTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include "Poco/Process.h"
#include "Poco/Pipe.h"
#include "Poco/PipeStream.h"
#include "Poco/Thread.h"
#include <csignal>


using Poco::Process;
Expand Down Expand Up @@ -239,6 +241,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))
Poco::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();
assert (rc == -SIGINT);
#endif // defined(POCO_OS_FAMILY_UNIX)
}


void ProcessTest::setUp()
{
}
Expand All @@ -259,6 +300,8 @@ CppUnit::Test* ProcessTest::suite()
CppUnit_addTest(pSuite, ProcessTest, testLaunchEnv);
CppUnit_addTest(pSuite, ProcessTest, testLaunchArgs);
CppUnit_addTest(pSuite, ProcessTest, testIsRunning);
CppUnit_addTest(pSuite, ProcessTest, testIsRunningAllowsForTermination);
CppUnit_addTest(pSuite, ProcessTest, testSignalExitCode);

return pSuite;
}
2 changes: 2 additions & 0 deletions Foundation/testsuite/src/ProcessTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class ProcessTest: public CppUnit::TestCase
void testLaunchEnv();
void testLaunchArgs();
void testIsRunning();
void testIsRunningAllowsForTermination();
void testSignalExitCode();

void setUp();
void tearDown();
Expand Down

0 comments on commit dbeab4f

Please sign in to comment.