poco/Foundation/include/Poco/ProcessRunner.h

232 lines
5.9 KiB
C
Raw Normal View History

Add ProcessRunner and PIDFile (#4225) * feat(Foundation): PIDFile and ProcessRunner #4064 * feat(Thread): optional signal blocking on POSIX #2978 * fix(ProcessRunner):remove logger, code enhancement #4225 * feat(Foundation): add PIDFile and ProcessRunner Tests #4064 * fix(Foundation): failing ProcessRunner Test #4064 * fix(PIDFile): remove append argument #4064 * remove Windows TODO from ProcessRunner #4064 * feat(ProcessRunnerTest): add line to checkTimeout #4064 * fix(ProcessRunner): add done flag to run() #4064 * fix(ProcessRunnerTest): add missing pidFile argument #4064 * chore(ProcessRunner): remove comments #4064 * fix(ProcessRunner): add runCount flag #4064 * fix(test): SharedLibrary and Class tests paths * fix(ProcessRunner): thread sanitizer reported data races #4064 * fix(build): pass env var to testrunner #4064 * chore(PIDFile): remove ; in comments #4064 * feat(ProcessRunner): add Win argument format #4064 * fix(Tests): add ProcessRunnerTest to vcxproj #4064 * fix(Tests): change path to TestApp #4064 * feat(Tests): windows processrunner tests #4064 * fix(Tests): duplicate ProcessRunnerTest in TestSuite vcxproj #4064 * fix(CodeQL): sw declaration hides variable #4064 * fix test binaries path for cmake * fix(Build): missing include/PIDFile.h buildWin #4064 * fix(Build): add PocoFoundation depend in buildWin #4064 * feat(ProcessRunner): test process launching multiple threads #2976 --------- Co-authored-by: Pavle <pavle@debian-gnu-linux-11.localdomain> Co-authored-by: Alex Fabijanic <alex@pocoproject.org>
2023-11-24 20:22:01 +01:00
//
// ProcessRunner.h
//
// Library: Foundation
// Package: Processes
// Module: ProcessRunner
//
// Definition of the ProcessRunner class.
//
// Copyright (c) 2023, Applied Informatics Software Engineering GmbH.
// Aleph ONE Software Engineering d.o.o.,
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Foundation_ProcessRunner_INCLUDED
#define Foundation_ProcessRunner_INCLUDED
#include "Poco/Foundation.h"
#include "Poco/Process.h"
#include "Poco/ProcessOptions.h"
#include "Poco/Runnable.h"
#include "Poco/Thread.h"
#include "Poco/Format.h"
#include "Poco/Stopwatch.h"
#include <atomic>
#include <vector>
namespace Poco {
class Foundation_API ProcessRunner: public Poco::Runnable
/// ProcessRunner is a wrapper class for `Poco::ProcessHandle.
/// It starts and terminates a process with enabled or disabled (default)
/// `stdio` pipes, and optionally waits for process PID to be created before
/// returning control to the caller. The process is spawned from an
/// internal thread. Starting/stopping the process may block up to
/// a certain (configurable) period of time.
///
/// ProcessRunner can hold and control only one process at a time, which
/// can be started/stopped multiple times during the ProcessRunner lifetime.
{
public:
using Args = Poco::Process::Args;
using PID = Poco::ProcessHandle::PID;
static const int NO_OUT = Poco::PROCESS_CLOSE_STDOUT|Poco::PROCESS_CLOSE_STDERR;
/// Constant to prevent std out and err from being received from the process.
ProcessRunner(const std::string& cmd,
const Args& args,
const std::string& pidFile = "",
int options = NO_OUT,
int timeout = 10, /*seconds*/
bool startProcess = true,
const Args& pidArgFmt = pidArgFormat());
/// Creates the ProcessRunner.
///
/// If `pidFile` is not empty, the starting of the process waits
/// until the pid file has been updated with the new pid, and
/// the stopping of the process waits until the pid file is gone.
/// Waiting is terminated after timeout seconds.
///
/// If `pidFile` is empty and `pidArgFmt` is not empty, autodetect
/// of PID file from `args` is attempted; the default PID file
/// argument format corresponds to the one used by
/// `Poco::Util::Application`
///
/// The `options` are passed to the process, defaulting to
/// closed stdio output pipes.
///
/// The `timeout` in seconds determines how long the ProcessRunner
/// waits for the process to start; if PID file name is provided or
/// autodetected from arguments, ProcessRunner will wait until the file
/// exists and contains the process PID or timeout expires (in which
/// case a TimeoutException is thrown).
///
/// If `startProcess` is true, the process is started on object creation.
~ProcessRunner();
/// Destroys the ProcessRunner.
PID pid() const;
/// Returns the process PID.
const std::string& pidFile() const;
/// Returns the process PID filename.
/// Returns empty string when pid filename
/// is not specified at construction, either
/// explicitly, or implicitly through
/// command line argument.
bool running() const;
/// Returns true if process is running.
void start();
/// Starts the process and waits for it to be fully initialized.
/// Process initialization completion is indicated by a new pid in
/// the pid file (if specified at construction, otherwise there
/// is no wating for pid).
/// If pid file is not specified, there is no waiting.
///
/// Attempting to start a started process results in
/// Poco::InvalidAccessException being thrown.
void stop();
/// Stops the process.
///
/// Calling stop() on a stopped process is a no-op.
std::string cmdLine() const;
/// Returns process full command line.
int result() const;
/// Returns process return code.
int runCount() const;
/// Returns the number of times the process has been executed.
const std::string& error() const;
/// Returns the error message.
Add ProcessRunner and PIDFile (#4225) * feat(Foundation): PIDFile and ProcessRunner #4064 * feat(Thread): optional signal blocking on POSIX #2978 * fix(ProcessRunner):remove logger, code enhancement #4225 * feat(Foundation): add PIDFile and ProcessRunner Tests #4064 * fix(Foundation): failing ProcessRunner Test #4064 * fix(PIDFile): remove append argument #4064 * remove Windows TODO from ProcessRunner #4064 * feat(ProcessRunnerTest): add line to checkTimeout #4064 * fix(ProcessRunner): add done flag to run() #4064 * fix(ProcessRunnerTest): add missing pidFile argument #4064 * chore(ProcessRunner): remove comments #4064 * fix(ProcessRunner): add runCount flag #4064 * fix(test): SharedLibrary and Class tests paths * fix(ProcessRunner): thread sanitizer reported data races #4064 * fix(build): pass env var to testrunner #4064 * chore(PIDFile): remove ; in comments #4064 * feat(ProcessRunner): add Win argument format #4064 * fix(Tests): add ProcessRunnerTest to vcxproj #4064 * fix(Tests): change path to TestApp #4064 * feat(Tests): windows processrunner tests #4064 * fix(Tests): duplicate ProcessRunnerTest in TestSuite vcxproj #4064 * fix(CodeQL): sw declaration hides variable #4064 * fix test binaries path for cmake * fix(Build): missing include/PIDFile.h buildWin #4064 * fix(Build): add PocoFoundation depend in buildWin #4064 * feat(ProcessRunner): test process launching multiple threads #2976 --------- Co-authored-by: Pavle <pavle@debian-gnu-linux-11.localdomain> Co-authored-by: Alex Fabijanic <alex@pocoproject.org>
2023-11-24 20:22:01 +01:00
private:
static const Poco::ProcessHandle::PID INVALID_PID = -1;
static const int RESULT_UNKNOWN = -1;
static Args pidArgFormat()
{
#if defined(POCO_OS_FAMILY_WINDOWS)
return Args{"-p", "--pidfile=", "/p", "/pidfile="};
#else
return Args{"-p", "--pidfile="};
#endif
}
void run();
/// Starts the process and waits for it to be fully initialized.
/// Process initialization completion is indicated by new pid in
/// the pid file. If pid file is not specified, there is no waiting.
void checkError();
Add ProcessRunner and PIDFile (#4225) * feat(Foundation): PIDFile and ProcessRunner #4064 * feat(Thread): optional signal blocking on POSIX #2978 * fix(ProcessRunner):remove logger, code enhancement #4225 * feat(Foundation): add PIDFile and ProcessRunner Tests #4064 * fix(Foundation): failing ProcessRunner Test #4064 * fix(PIDFile): remove append argument #4064 * remove Windows TODO from ProcessRunner #4064 * feat(ProcessRunnerTest): add line to checkTimeout #4064 * fix(ProcessRunner): add done flag to run() #4064 * fix(ProcessRunnerTest): add missing pidFile argument #4064 * chore(ProcessRunner): remove comments #4064 * fix(ProcessRunner): add runCount flag #4064 * fix(test): SharedLibrary and Class tests paths * fix(ProcessRunner): thread sanitizer reported data races #4064 * fix(build): pass env var to testrunner #4064 * chore(PIDFile): remove ; in comments #4064 * feat(ProcessRunner): add Win argument format #4064 * fix(Tests): add ProcessRunnerTest to vcxproj #4064 * fix(Tests): change path to TestApp #4064 * feat(Tests): windows processrunner tests #4064 * fix(Tests): duplicate ProcessRunnerTest in TestSuite vcxproj #4064 * fix(CodeQL): sw declaration hides variable #4064 * fix test binaries path for cmake * fix(Build): missing include/PIDFile.h buildWin #4064 * fix(Build): add PocoFoundation depend in buildWin #4064 * feat(ProcessRunner): test process launching multiple threads #2976 --------- Co-authored-by: Pavle <pavle@debian-gnu-linux-11.localdomain> Co-authored-by: Alex Fabijanic <alex@pocoproject.org>
2023-11-24 20:22:01 +01:00
/// If timeout is exceeded, throws TimeoutException with `msg`
/// message.
void checkTimeout(const std::string& msg);
/// If timeout is exceeded, throws TimeoutException with `msg`
/// message.
void checkStatus(const std::string& msg, bool tOut = true);
/// If there were andy errors during process start/stop,
/// throws RuntimeException with the error message;
/// otherwise, if tOut is true and timeout is exceeded, throws
/// TimeoutException with `msg` message.
void setError(const std::string& msg);
/// Sets the error message.
Add ProcessRunner and PIDFile (#4225) * feat(Foundation): PIDFile and ProcessRunner #4064 * feat(Thread): optional signal blocking on POSIX #2978 * fix(ProcessRunner):remove logger, code enhancement #4225 * feat(Foundation): add PIDFile and ProcessRunner Tests #4064 * fix(Foundation): failing ProcessRunner Test #4064 * fix(PIDFile): remove append argument #4064 * remove Windows TODO from ProcessRunner #4064 * feat(ProcessRunnerTest): add line to checkTimeout #4064 * fix(ProcessRunner): add done flag to run() #4064 * fix(ProcessRunnerTest): add missing pidFile argument #4064 * chore(ProcessRunner): remove comments #4064 * fix(ProcessRunner): add runCount flag #4064 * fix(test): SharedLibrary and Class tests paths * fix(ProcessRunner): thread sanitizer reported data races #4064 * fix(build): pass env var to testrunner #4064 * chore(PIDFile): remove ; in comments #4064 * feat(ProcessRunner): add Win argument format #4064 * fix(Tests): add ProcessRunnerTest to vcxproj #4064 * fix(Tests): change path to TestApp #4064 * feat(Tests): windows processrunner tests #4064 * fix(Tests): duplicate ProcessRunnerTest in TestSuite vcxproj #4064 * fix(CodeQL): sw declaration hides variable #4064 * fix test binaries path for cmake * fix(Build): missing include/PIDFile.h buildWin #4064 * fix(Build): add PocoFoundation depend in buildWin #4064 * feat(ProcessRunner): test process launching multiple threads #2976 --------- Co-authored-by: Pavle <pavle@debian-gnu-linux-11.localdomain> Co-authored-by: Alex Fabijanic <alex@pocoproject.org>
2023-11-24 20:22:01 +01:00
Poco::Thread _t;
std::string _cmd;
Args _args;
std::atomic<PID> _pid;
std::string _pidFile;
int _options;
int _timeout;
std::atomic<Poco::ProcessHandle*> _pPH;
std::atomic<bool> _started;
std::atomic<int> _rc;
std::atomic<int> _runCount;
Stopwatch _sw;
std::string _error;
mutable Poco::FastMutex _mutex;
Add ProcessRunner and PIDFile (#4225) * feat(Foundation): PIDFile and ProcessRunner #4064 * feat(Thread): optional signal blocking on POSIX #2978 * fix(ProcessRunner):remove logger, code enhancement #4225 * feat(Foundation): add PIDFile and ProcessRunner Tests #4064 * fix(Foundation): failing ProcessRunner Test #4064 * fix(PIDFile): remove append argument #4064 * remove Windows TODO from ProcessRunner #4064 * feat(ProcessRunnerTest): add line to checkTimeout #4064 * fix(ProcessRunner): add done flag to run() #4064 * fix(ProcessRunnerTest): add missing pidFile argument #4064 * chore(ProcessRunner): remove comments #4064 * fix(ProcessRunner): add runCount flag #4064 * fix(test): SharedLibrary and Class tests paths * fix(ProcessRunner): thread sanitizer reported data races #4064 * fix(build): pass env var to testrunner #4064 * chore(PIDFile): remove ; in comments #4064 * feat(ProcessRunner): add Win argument format #4064 * fix(Tests): add ProcessRunnerTest to vcxproj #4064 * fix(Tests): change path to TestApp #4064 * feat(Tests): windows processrunner tests #4064 * fix(Tests): duplicate ProcessRunnerTest in TestSuite vcxproj #4064 * fix(CodeQL): sw declaration hides variable #4064 * fix test binaries path for cmake * fix(Build): missing include/PIDFile.h buildWin #4064 * fix(Build): add PocoFoundation depend in buildWin #4064 * feat(ProcessRunner): test process launching multiple threads #2976 --------- Co-authored-by: Pavle <pavle@debian-gnu-linux-11.localdomain> Co-authored-by: Alex Fabijanic <alex@pocoproject.org>
2023-11-24 20:22:01 +01:00
};
//
// inlines
//
inline const std::string& ProcessRunner::pidFile() const
{
return _pidFile;
}
inline bool ProcessRunner::running() const
{
return _pid != INVALID_PID;
}
inline ProcessRunner::PID ProcessRunner::pid() const
{
return _pid;
}
inline int ProcessRunner::result() const
{
return _rc;
}
inline int ProcessRunner::runCount() const
{
return _runCount;
}
inline void ProcessRunner::setError(const std::string& msg)
{
_error = Poco::format("ProcessRunner(%s): %s", cmdLine(), msg);
}
inline const std::string& ProcessRunner::error() const
{
Poco::FastMutex::ScopedLock l(_mutex);
return _error;
}
Add ProcessRunner and PIDFile (#4225) * feat(Foundation): PIDFile and ProcessRunner #4064 * feat(Thread): optional signal blocking on POSIX #2978 * fix(ProcessRunner):remove logger, code enhancement #4225 * feat(Foundation): add PIDFile and ProcessRunner Tests #4064 * fix(Foundation): failing ProcessRunner Test #4064 * fix(PIDFile): remove append argument #4064 * remove Windows TODO from ProcessRunner #4064 * feat(ProcessRunnerTest): add line to checkTimeout #4064 * fix(ProcessRunner): add done flag to run() #4064 * fix(ProcessRunnerTest): add missing pidFile argument #4064 * chore(ProcessRunner): remove comments #4064 * fix(ProcessRunner): add runCount flag #4064 * fix(test): SharedLibrary and Class tests paths * fix(ProcessRunner): thread sanitizer reported data races #4064 * fix(build): pass env var to testrunner #4064 * chore(PIDFile): remove ; in comments #4064 * feat(ProcessRunner): add Win argument format #4064 * fix(Tests): add ProcessRunnerTest to vcxproj #4064 * fix(Tests): change path to TestApp #4064 * feat(Tests): windows processrunner tests #4064 * fix(Tests): duplicate ProcessRunnerTest in TestSuite vcxproj #4064 * fix(CodeQL): sw declaration hides variable #4064 * fix test binaries path for cmake * fix(Build): missing include/PIDFile.h buildWin #4064 * fix(Build): add PocoFoundation depend in buildWin #4064 * feat(ProcessRunner): test process launching multiple threads #2976 --------- Co-authored-by: Pavle <pavle@debian-gnu-linux-11.localdomain> Co-authored-by: Alex Fabijanic <alex@pocoproject.org>
2023-11-24 20:22:01 +01:00
} // namespace Poco
#endif // Foundation_ProcessRunner_INCLUDED