mirror of
https://github.com/pocoproject/poco.git
synced 2024-12-12 10:13:51 +01:00
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>
This commit is contained in:
parent
904075e1f1
commit
70bb3a40de
@ -11,7 +11,7 @@
|
||||
|
||||
#ifdef Data_API
|
||||
#define SQLParser_API Data_API
|
||||
#ifdef Data_EXPORTS
|
||||
#if defined(Data_EXPORTS) && !defined(SQLParser_EXPORTS)
|
||||
#define SQLParser_EXPORTS
|
||||
#endif
|
||||
#else
|
||||
|
@ -1093,6 +1093,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\pcre2_valid_utf.c" />
|
||||
<ClCompile Include="src\pcre2_xclass.c" />
|
||||
<ClCompile Include="src\PIDFile.cpp" />
|
||||
<ClCompile Include="src\Pipe.cpp" />
|
||||
<ClCompile Include="src\PipeImpl.cpp" />
|
||||
<ClCompile Include="src\PipeImpl_DUMMY.cpp">
|
||||
@ -1168,6 +1169,7 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ProcessRunner.cpp" />
|
||||
<ClCompile Include="src\PurgeStrategy.cpp" />
|
||||
<ClCompile Include="src\Random.cpp" />
|
||||
<ClCompile Include="src\RandomStream.cpp" />
|
||||
@ -1655,6 +1657,7 @@
|
||||
<ClInclude Include="include\Poco\Path_WIN32U.h" />
|
||||
<ClInclude Include="include\Poco\PatternFormatter.h" />
|
||||
<ClInclude Include="include\Poco\PBKDF2Engine.h" />
|
||||
<ClInclude Include="include\Poco\PIDFile.h" />
|
||||
<ClInclude Include="include\Poco\Pipe.h" />
|
||||
<ClInclude Include="include\Poco\PipeImpl.h" />
|
||||
<ClInclude Include="include\Poco\PipeImpl_DUMMY.h" />
|
||||
@ -1673,6 +1676,7 @@
|
||||
<ClInclude Include="include\Poco\Process.h" />
|
||||
<ClInclude Include="include\Poco\Process_UNIX.h" />
|
||||
<ClInclude Include="include\Poco\Process_WIN32U.h" />
|
||||
<ClInclude Include="include\Poco\ProcessRunner.h" />
|
||||
<ClInclude Include="include\Poco\PurgeStrategy.h" />
|
||||
<ClInclude Include="include\Poco\Random.h" />
|
||||
<ClInclude Include="include\Poco\RandomStream.h" />
|
||||
|
@ -642,6 +642,9 @@
|
||||
<ClCompile Include="src\NamedMutex_WIN32U.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\PIDFile.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Pipe.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -669,6 +672,9 @@
|
||||
<ClCompile Include="src\Process_WIN32U.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ProcessRunner.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\SharedMemory.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -1514,6 +1520,9 @@
|
||||
<ClInclude Include="include\Poco\NamedMutex_WIN32U.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\PIDFile.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\Pipe.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -1541,6 +1550,9 @@
|
||||
<ClInclude Include="include\Poco\Process_WIN32U.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\ProcessRunner.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\SharedMemory.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1093,6 +1093,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\pcre2_valid_utf.c" />
|
||||
<ClCompile Include="src\pcre2_xclass.c" />
|
||||
<ClCompile Include="src\PIDFile.cpp" />
|
||||
<ClCompile Include="src\Pipe.cpp" />
|
||||
<ClCompile Include="src\PipeImpl.cpp" />
|
||||
<ClCompile Include="src\PipeImpl_DUMMY.cpp">
|
||||
@ -1168,6 +1169,7 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ProcessRunner.cpp" />
|
||||
<ClCompile Include="src\PurgeStrategy.cpp" />
|
||||
<ClCompile Include="src\Random.cpp" />
|
||||
<ClCompile Include="src\RandomStream.cpp" />
|
||||
@ -1655,6 +1657,7 @@
|
||||
<ClInclude Include="include\Poco\Path_WIN32U.h" />
|
||||
<ClInclude Include="include\Poco\PatternFormatter.h" />
|
||||
<ClInclude Include="include\Poco\PBKDF2Engine.h" />
|
||||
<ClInclude Include="include\Poco\PIDFile.h" />
|
||||
<ClInclude Include="include\Poco\Pipe.h" />
|
||||
<ClInclude Include="include\Poco\PipeImpl.h" />
|
||||
<ClInclude Include="include\Poco\PipeImpl_DUMMY.h" />
|
||||
@ -1673,6 +1676,7 @@
|
||||
<ClInclude Include="include\Poco\Process.h" />
|
||||
<ClInclude Include="include\Poco\Process_UNIX.h" />
|
||||
<ClInclude Include="include\Poco\Process_WIN32U.h" />
|
||||
<ClInclude Include="include\Poco\ProcessRunner.h" />
|
||||
<ClInclude Include="include\Poco\PurgeStrategy.h" />
|
||||
<ClInclude Include="include\Poco\Random.h" />
|
||||
<ClInclude Include="include\Poco\RandomStream.h" />
|
||||
|
@ -642,6 +642,9 @@
|
||||
<ClCompile Include="src\NamedMutex_WIN32U.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\PIDFile.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Pipe.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -669,6 +672,9 @@
|
||||
<ClCompile Include="src\Process_WIN32U.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ProcessRunner.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\SharedMemory.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -1514,6 +1520,9 @@
|
||||
<ClInclude Include="include\Poco\NamedMutex_WIN32U.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\PIDFile.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\Pipe.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -1541,6 +1550,9 @@
|
||||
<ClInclude Include="include\Poco\Process_WIN32U.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\ProcessRunner.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\SharedMemory.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1099,6 +1099,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\pcre2_valid_utf.c" />
|
||||
<ClCompile Include="src\pcre2_xclass.c" />
|
||||
<ClCompile Include="src\PIDFile.cpp" />
|
||||
<ClCompile Include="src\Pipe.cpp" />
|
||||
<ClCompile Include="src\PipeImpl.cpp" />
|
||||
<ClCompile Include="src\PipeImpl_DUMMY.cpp">
|
||||
@ -1174,6 +1175,7 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ProcessRunner.cpp" />
|
||||
<ClCompile Include="src\PurgeStrategy.cpp" />
|
||||
<ClCompile Include="src\Random.cpp" />
|
||||
<ClCompile Include="src\RandomStream.cpp" />
|
||||
@ -1661,6 +1663,7 @@
|
||||
<ClInclude Include="include\Poco\Path_WIN32U.h" />
|
||||
<ClInclude Include="include\Poco\PatternFormatter.h" />
|
||||
<ClInclude Include="include\Poco\PBKDF2Engine.h" />
|
||||
<ClInclude Include="include\Poco\PIDFile.h" />
|
||||
<ClInclude Include="include\Poco\Pipe.h" />
|
||||
<ClInclude Include="include\Poco\PipeImpl.h" />
|
||||
<ClInclude Include="include\Poco\PipeImpl_DUMMY.h" />
|
||||
@ -1679,6 +1682,7 @@
|
||||
<ClInclude Include="include\Poco\Process.h" />
|
||||
<ClInclude Include="include\Poco\Process_UNIX.h" />
|
||||
<ClInclude Include="include\Poco\Process_WIN32U.h" />
|
||||
<ClInclude Include="include\Poco\ProcessRunner.h" />
|
||||
<ClInclude Include="include\Poco\PurgeStrategy.h" />
|
||||
<ClInclude Include="include\Poco\Random.h" />
|
||||
<ClInclude Include="include\Poco\RandomStream.h" />
|
||||
|
@ -642,6 +642,9 @@
|
||||
<ClCompile Include="src\NamedMutex_WIN32U.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\PIDFile.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Pipe.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -669,6 +672,9 @@
|
||||
<ClCompile Include="src\Process_WIN32U.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ProcessRunner.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\SharedMemory.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -1514,6 +1520,9 @@
|
||||
<ClInclude Include="include\Poco\NamedMutex_WIN32U.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\PIDFile.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\Pipe.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -1541,6 +1550,9 @@
|
||||
<ClInclude Include="include\Poco\Process_WIN32U.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\ProcessRunner.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\SharedMemory.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1550,6 +1550,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\pcre2_valid_utf.c" />
|
||||
<ClCompile Include="src\pcre2_xclass.c" />
|
||||
<ClCompile Include="src\PIDFile.cpp" />
|
||||
<ClCompile Include="src\Pipe.cpp" />
|
||||
<ClCompile Include="src\PipeImpl.cpp" />
|
||||
<ClCompile Include="src\PipeImpl_DUMMY.cpp">
|
||||
@ -1655,6 +1656,7 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release_static_mt|ARM64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ProcessRunner.cpp" />
|
||||
<ClCompile Include="src\PurgeStrategy.cpp" />
|
||||
<ClCompile Include="src\Random.cpp" />
|
||||
<ClCompile Include="src\RandomStream.cpp" />
|
||||
@ -2244,6 +2246,7 @@
|
||||
<ClInclude Include="include\Poco\Path_WIN32U.h" />
|
||||
<ClInclude Include="include\Poco\PatternFormatter.h" />
|
||||
<ClInclude Include="include\Poco\PBKDF2Engine.h" />
|
||||
<ClInclude Include="include\Poco\PIDFile.h" />
|
||||
<ClInclude Include="include\Poco\Pipe.h" />
|
||||
<ClInclude Include="include\Poco\PipeImpl.h" />
|
||||
<ClInclude Include="include\Poco\PipeImpl_DUMMY.h" />
|
||||
@ -2262,6 +2265,7 @@
|
||||
<ClInclude Include="include\Poco\Process.h" />
|
||||
<ClInclude Include="include\Poco\Process_UNIX.h" />
|
||||
<ClInclude Include="include\Poco\Process_WIN32U.h" />
|
||||
<ClInclude Include="include\Poco\ProcessRunner.h" />
|
||||
<ClInclude Include="include\Poco\PurgeStrategy.h" />
|
||||
<ClInclude Include="include\Poco\Random.h" />
|
||||
<ClInclude Include="include\Poco\RandomStream.h" />
|
||||
|
@ -642,6 +642,9 @@
|
||||
<ClCompile Include="src\NamedMutex_WIN32U.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\PIDFile.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Pipe.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -669,6 +672,9 @@
|
||||
<ClCompile Include="src\Process_WIN32U.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ProcessRunner.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\SharedMemory.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -1514,6 +1520,9 @@
|
||||
<ClInclude Include="include\Poco\NamedMutex_WIN32U.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\PIDFile.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\Pipe.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -1541,6 +1550,9 @@
|
||||
<ClInclude Include="include\Poco\Process_WIN32U.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\ProcessRunner.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Poco\SharedMemory.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -19,7 +19,7 @@ objects = ArchiveStrategy Ascii ASCIIEncoding AsyncChannel ActiveThreadPool\
|
||||
NestedDiagnosticContext Notification NotificationCenter \
|
||||
NotificationQueue PriorityNotificationQueue TimedNotificationQueue \
|
||||
NullStream NumberFormatter NumberParser NumericString AbstractObserver \
|
||||
Path PatternFormatter Process PurgeStrategy RWLock Random RandomStream \
|
||||
Path PatternFormatter PIDFile Process ProcessRunner PurgeStrategy RWLock Random RandomStream \
|
||||
DirectoryIteratorStrategy RegularExpression RefCountedObject Runnable RotateStrategy \
|
||||
SHA1Engine SHA2Engine Semaphore SharedLibrary SimpleFileChannel \
|
||||
SignalHandler SplitterChannel SortedDirectoryIterator Stopwatch StreamChannel \
|
||||
|
101
Foundation/include/Poco/PIDFile.h
Normal file
101
Foundation/include/Poco/PIDFile.h
Normal file
@ -0,0 +1,101 @@
|
||||
//
|
||||
// PIDFile.h
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Processes
|
||||
// Module: PIDFile
|
||||
//
|
||||
// Definition of the PIDFile 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_PIDFile_INCLUDED
|
||||
#define Foundation_PIDFile_INCLUDED
|
||||
|
||||
|
||||
#include "Poco/Foundation.h"
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
class Foundation_API PIDFile
|
||||
/// A utility class, creating process ID file on
|
||||
/// construction and deleting it on destruction.
|
||||
{
|
||||
public:
|
||||
using Ptr = std::unique_ptr<PIDFile>;
|
||||
|
||||
static const int INVALID_PID = -1;
|
||||
|
||||
PIDFile();
|
||||
/// Creates the PIDFile.
|
||||
|
||||
PIDFile(const std::string& fileName, bool write = true);
|
||||
/// Creates the PIDFile.
|
||||
/// If `fileName` is not empty, creates the PID file.
|
||||
/// If `write` is true, the file is written.
|
||||
|
||||
~PIDFile();
|
||||
/// Destroys the PIDFile.
|
||||
/// If fileName is not empty, deletes the PID file.
|
||||
|
||||
const std::string& getName() const;
|
||||
/// Returns the file name.
|
||||
|
||||
void setName(const std::string& fileName);
|
||||
/// Sets the file name.
|
||||
|
||||
void create();
|
||||
/// Creates the file and writes PID into it.
|
||||
|
||||
void destroy();
|
||||
/// Deletes the PID file and invalidates the held PID.
|
||||
|
||||
int getPID() const;
|
||||
/// Returns the PID.
|
||||
|
||||
bool exists() const;
|
||||
/// Returns true if PID file exists and its content is
|
||||
/// equal to the held PID.
|
||||
|
||||
static bool contains(const std::string& fileName, int pid);
|
||||
/// Returns true if the `fileName` contains the given `pid`.
|
||||
|
||||
static std::string& getFileName(std::string& pidFile);
|
||||
/// Returns the file name.
|
||||
|
||||
private:
|
||||
|
||||
std::string _fileName;
|
||||
int _pid = INVALID_PID;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// inlines
|
||||
//
|
||||
|
||||
inline const std::string& PIDFile::getName() const
|
||||
{
|
||||
return _fileName;
|
||||
}
|
||||
|
||||
|
||||
inline int PIDFile::getPID() const
|
||||
{
|
||||
return _pid;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
|
||||
#endif // Foundation_ProcessRunner_INCLUDED
|
199
Foundation/include/Poco/ProcessRunner.h
Normal file
199
Foundation/include/Poco/ProcessRunner.h
Normal file
@ -0,0 +1,199 @@
|
||||
//
|
||||
// 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.
|
||||
|
||||
|
||||
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 checkTimeout(const Poco::Stopwatch& sw, const std::string& msg);
|
||||
/// If timeout is exceeded, throws TimeoutException with `msg`
|
||||
/// message.
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
||||
|
||||
|
||||
#endif // Foundation_ProcessRunner_INCLUDED
|
@ -23,6 +23,7 @@
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <atomic>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@ -42,7 +43,7 @@ public:
|
||||
int tryWait() const;
|
||||
|
||||
private:
|
||||
pid_t _pid;
|
||||
std::atomic<pid_t> _pid;
|
||||
};
|
||||
|
||||
|
||||
|
@ -74,11 +74,23 @@ public:
|
||||
POLICY_DEFAULT = POLICY_DEFAULT_IMPL
|
||||
};
|
||||
|
||||
Thread();
|
||||
Thread(uint32_t sigMask = 0);
|
||||
/// Creates a thread. Call start() to start it.
|
||||
///
|
||||
/// The optional sigMask parameter specifies which signals should be blocked.
|
||||
/// To block a specific signal, set the corresponding bit in the sigMask.
|
||||
/// Multiple bits can be set in the mask to block multiple signals if needed.
|
||||
///
|
||||
/// Available on POSIX platforms only
|
||||
|
||||
Thread(const std::string& name);
|
||||
Thread(const std::string& name, uint32_t sigMask = 0);
|
||||
/// Creates a named thread. Call start() to start it.
|
||||
///
|
||||
/// The optional sigMask parameter specifies which signals should be blocked.
|
||||
/// To block a specific signal, set the corresponding bit in the sigMask.
|
||||
/// Multiple bits can be set in the mask to block multiple signals if needed.
|
||||
///
|
||||
/// Available on POSIX platforms only
|
||||
|
||||
~Thread();
|
||||
/// Destroys the thread.
|
||||
|
@ -76,6 +76,7 @@ public:
|
||||
static int getMaxOSPriorityImpl(int policy);
|
||||
void setStackSizeImpl(int size);
|
||||
int getStackSizeImpl() const;
|
||||
void setSignalMaskImpl(uint32_t sigMask);
|
||||
void startImpl(SharedPtr<Runnable> pTarget);
|
||||
void joinImpl();
|
||||
bool joinImpl(long milliseconds);
|
||||
|
122
Foundation/src/PIDFile.cpp
Normal file
122
Foundation/src/PIDFile.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
//
|
||||
// PIDFile.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Processes
|
||||
// Module: PIDFile
|
||||
//
|
||||
// Copyright (c) 2023, Applied Informatics Software Engineering GmbH.
|
||||
// Aleph ONE Software Engineering d.o.o.,
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/PIDFile.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Process.h"
|
||||
#include "Poco/FileStream.h"
|
||||
#include <fstream>
|
||||
|
||||
|
||||
using Poco::Path;
|
||||
using Poco::File;
|
||||
using Poco::Process;
|
||||
using Poco::FileInputStream;
|
||||
using Poco::FileOutputStream;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
PIDFile::PIDFile()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PIDFile::PIDFile(const std::string& fileName, bool write):
|
||||
_fileName(fileName)
|
||||
{
|
||||
if (write) create();
|
||||
}
|
||||
|
||||
|
||||
PIDFile::~PIDFile()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
|
||||
void PIDFile::setName(const std::string& fileName)
|
||||
{
|
||||
destroy();
|
||||
_fileName = fileName;
|
||||
create();
|
||||
}
|
||||
|
||||
|
||||
void PIDFile::create()
|
||||
{
|
||||
if (!_fileName.empty())
|
||||
{
|
||||
Path p(getFileName(_fileName));
|
||||
if (!File(p.makeParent()).exists())
|
||||
File(p).createDirectories();
|
||||
_pid = static_cast<int>(Process::id());
|
||||
FileOutputStream fos(_fileName);
|
||||
fos << _pid; fos.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PIDFile::destroy()
|
||||
{
|
||||
if (!_fileName.empty())
|
||||
{
|
||||
File f(_fileName);
|
||||
if (f.exists()) f.remove();
|
||||
_fileName.clear();
|
||||
}
|
||||
_pid = INVALID_PID;
|
||||
}
|
||||
|
||||
|
||||
bool PIDFile::exists() const
|
||||
{
|
||||
if (File(_fileName).exists())
|
||||
{
|
||||
FileInputStream fis(_fileName);
|
||||
int fPID = 0;
|
||||
if (fis.peek() != std::ifstream::traits_type::eof())
|
||||
fis >> fPID;
|
||||
return fPID == _pid;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool PIDFile::contains(const std::string& fileName, int pid)
|
||||
{
|
||||
if (File(fileName).exists())
|
||||
{
|
||||
FileInputStream fis(fileName);
|
||||
int fPID = 0;
|
||||
if (fis.peek() != std::ifstream::traits_type::eof())
|
||||
fis >> fPID;
|
||||
return fPID == pid;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::string& PIDFile::getFileName(std::string& pidFile)
|
||||
{
|
||||
Path p(pidFile);
|
||||
pidFile = p.makeAbsolute().toString();
|
||||
return pidFile;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
217
Foundation/src/ProcessRunner.cpp
Normal file
217
Foundation/src/ProcessRunner.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
//
|
||||
// ProcessRunner.cpp
|
||||
//
|
||||
// Library: Foundation
|
||||
// Package: Processes
|
||||
// Module: ProcessRunner
|
||||
//
|
||||
// Copyright (c) 2023, Applied Informatics Software Engineering GmbH.
|
||||
// Aleph ONE Software Engineering d.o.o.,
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/ProcessRunner.h"
|
||||
#include "Poco/PIDFile.h"
|
||||
#include "Poco/FileStream.h"
|
||||
#include "Poco/AutoPtr.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/String.h"
|
||||
#include <fstream>
|
||||
|
||||
|
||||
using Poco::Thread;
|
||||
using Poco::Process;
|
||||
using Poco::ProcessHandle;
|
||||
using Poco::FileInputStream;
|
||||
using Poco::AutoPtr;
|
||||
using Poco::File;
|
||||
using Poco::Path;
|
||||
using Poco::Stopwatch;
|
||||
|
||||
|
||||
namespace Poco {
|
||||
|
||||
|
||||
ProcessRunner::ProcessRunner(const std::string& cmd,
|
||||
const Args& args,
|
||||
const std::string& pidFile,
|
||||
int options,
|
||||
int timeout,
|
||||
bool startProcess,
|
||||
const Args& pidArgFmt): _cmd(cmd),
|
||||
_args(args),
|
||||
_pid(INVALID_PID),
|
||||
_pidFile(pidFile),
|
||||
_options(options),
|
||||
_timeout(timeout),
|
||||
_pPH(nullptr),
|
||||
_started(false),
|
||||
_rc(RESULT_UNKNOWN),
|
||||
_runCount(0)
|
||||
{
|
||||
if (_pidFile.empty() && !_args.empty() && !pidArgFmt.empty())
|
||||
{
|
||||
for (const auto& fmt : pidArgFmt)
|
||||
{
|
||||
for (const auto& arg : _args)
|
||||
{
|
||||
std::string a = Poco::trim(arg);
|
||||
std::size_t pos = a.find(fmt);
|
||||
if (pos == 0)
|
||||
{
|
||||
_pidFile = a.substr(fmt.length());
|
||||
PIDFile::getFileName(_pidFile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (startProcess) start();
|
||||
}
|
||||
|
||||
|
||||
ProcessRunner::~ProcessRunner()
|
||||
{
|
||||
try
|
||||
{
|
||||
stop();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
poco_unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string ProcessRunner::cmdLine() const
|
||||
{
|
||||
std::string cmdL = _cmd + ' ';
|
||||
auto it = _args.begin();
|
||||
auto end = _args.end();
|
||||
for (; it != end;)
|
||||
{
|
||||
cmdL.append(*it);
|
||||
if (++it == end) break;
|
||||
cmdL.append(1, ' ');
|
||||
}
|
||||
return cmdL;
|
||||
}
|
||||
|
||||
|
||||
void ProcessRunner::run()
|
||||
{
|
||||
ProcessHandle* pPH = nullptr;
|
||||
try
|
||||
{
|
||||
_pPH = pPH = new ProcessHandle(Process::launch(_cmd, _args, _options));
|
||||
_pid = pPH->id();
|
||||
_rc = pPH->wait();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
|
||||
_pid = INVALID_PID;
|
||||
_pPH = nullptr;
|
||||
++_runCount;
|
||||
delete pPH;
|
||||
}
|
||||
|
||||
|
||||
void ProcessRunner::stop()
|
||||
{
|
||||
if (_started)
|
||||
{
|
||||
PID pid;
|
||||
Stopwatch sw; sw.start();
|
||||
if (_pPH.exchange(nullptr) && ((pid = _pid.exchange(INVALID_PID))) != INVALID_PID)
|
||||
{
|
||||
while (Process::isRunning(pid))
|
||||
{
|
||||
if (pid > 0)
|
||||
{
|
||||
Process::requestTermination(pid);
|
||||
checkTimeout(sw, "Waiting for process termination");
|
||||
}
|
||||
else throw Poco::IllegalStateException("Invalid PID, can;t terminate process");
|
||||
}
|
||||
_t.join();
|
||||
}
|
||||
|
||||
if (!_pidFile.empty())
|
||||
{
|
||||
if (!_pidFile.empty())
|
||||
{
|
||||
File pidFile(_pidFile);
|
||||
_pidFile.clear();
|
||||
std::string msg;
|
||||
Poco::format(msg, "Waiting for PID file (pidFile: '%s')", _pidFile);
|
||||
sw.restart();
|
||||
while (pidFile.exists())
|
||||
checkTimeout(sw, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
_started.store(false);
|
||||
}
|
||||
|
||||
|
||||
void ProcessRunner::checkTimeout(const Stopwatch& sw, const std::string& msg)
|
||||
{
|
||||
if (sw.elapsedSeconds() > _timeout)
|
||||
{
|
||||
throw Poco::TimeoutException(
|
||||
Poco::format("ProcessRunner::checkTimeout(): %s", msg));
|
||||
}
|
||||
Thread::sleep(10);
|
||||
}
|
||||
|
||||
|
||||
void ProcessRunner::start()
|
||||
{
|
||||
if (!_started.exchange(true))
|
||||
{
|
||||
int prevRunCnt = runCount();
|
||||
|
||||
_t.start(*this);
|
||||
|
||||
std::string msg;
|
||||
Poco::format(msg, "Waiting for process to start (pidFile: '%s')", _pidFile);
|
||||
Stopwatch sw; sw.start();
|
||||
|
||||
// wait for the process to be either running or completed by monitoring run counts.
|
||||
while (!running() && prevRunCnt >= runCount()) checkTimeout(sw, msg);
|
||||
|
||||
// we could wait for the process handle != INVALID_PID,
|
||||
// but if pidFile name was given, we should wait for
|
||||
// the process to write it
|
||||
if (!_pidFile.empty())
|
||||
{
|
||||
sw.restart();
|
||||
// wait until process is fully initialized
|
||||
File pidFile(_pidFile);
|
||||
while (!pidFile.exists())
|
||||
checkTimeout(sw, "waiting for PID file");
|
||||
|
||||
// verify that the file content is actually the process PID
|
||||
FileInputStream fis(_pidFile);
|
||||
int fPID = 0;
|
||||
if (fis.peek() != std::ifstream::traits_type::eof())
|
||||
fis >> fPID;
|
||||
while (fPID != pid())
|
||||
{
|
||||
fis.clear(); fis.seekg(0); fis >> fPID;
|
||||
checkTimeout(sw, Poco::format("waiting for new PID (%s)", _pidFile));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
throw Poco::InvalidAccessException("start() called on started ProcessRunner");
|
||||
}
|
||||
|
||||
|
||||
} // namespace Poco
|
@ -88,21 +88,27 @@ private:
|
||||
} // namespace
|
||||
|
||||
|
||||
Thread::Thread():
|
||||
Thread::Thread(uint32_t sigMask):
|
||||
_id(uniqueId()),
|
||||
_pTLS(0),
|
||||
_event(true)
|
||||
{
|
||||
setNameImpl(makeName());
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
setSignalMaskImpl(sigMask);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Thread::Thread(const std::string& name):
|
||||
Thread::Thread(const std::string& name, uint32_t sigMask):
|
||||
_id(uniqueId()),
|
||||
_pTLS(0),
|
||||
_event(true)
|
||||
{
|
||||
setNameImpl(name);
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
setSignalMaskImpl(sigMask);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -257,6 +257,21 @@ void ThreadImpl::setStackSizeImpl(int size)
|
||||
}
|
||||
|
||||
|
||||
void ThreadImpl::setSignalMaskImpl(uint32_t sigMask)
|
||||
{
|
||||
sigset_t sset;
|
||||
sigemptyset(&sset);
|
||||
|
||||
for (int sig = 0; sig < sizeof(uint32_t) * 8; ++sig)
|
||||
{
|
||||
if ((sigMask & (1 << sig)) != 0)
|
||||
sigaddset(&sset, sig);
|
||||
}
|
||||
|
||||
pthread_sigmask(SIG_BLOCK, &sset, 0);
|
||||
}
|
||||
|
||||
|
||||
void ThreadImpl::startImpl(SharedPtr<Runnable> pTarget)
|
||||
{
|
||||
{
|
||||
|
@ -20,7 +20,7 @@ objects = ActiveMethodTest ActivityTest ActiveDispatcherTest \
|
||||
NDCTest NotificationCenterTest NotificationQueueTest \
|
||||
PriorityNotificationQueueTest TimedNotificationQueueTest \
|
||||
NotificationsTestSuite NullStreamTest NumberFormatterTest \
|
||||
NumberParserTest PathTest PatternFormatterTest PBKDF2EngineTest RWLockTest \
|
||||
NumberParserTest PathTest PatternFormatterTest PBKDF2EngineTest ProcessRunnerTest RWLockTest \
|
||||
RandomStreamTest RandomTest RegularExpressionTest SHA1EngineTest SHA2EngineTest \
|
||||
SemaphoreTest ConditionTest SharedLibraryTest SharedLibraryTestSuite \
|
||||
SimpleFileChannelTest StopwatchTest \
|
||||
|
@ -344,7 +344,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug_shared|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
@ -361,8 +361,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;iphlpapi.lib;PocoFoundationd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>bin\TestAppd.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>bin\TestAppd.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -372,7 +373,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug_shared|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
@ -388,8 +389,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;iphlpapi.lib;PocoFoundationd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>bin64\TestAppd.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>bin64\TestAppd.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -398,7 +400,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug_shared|ARM64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
@ -414,8 +416,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;iphlpapi.lib;PocoFoundationd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>binA64\TestAppd.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\libA64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\libA64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>binA64\TestAppd.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -428,7 +431,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;WINVER=0x0500;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
@ -445,8 +448,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;iphlpapi.lib;PocoFoundation.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>bin\TestApp.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>
|
||||
</ProgramDatabaseFile>
|
||||
@ -463,7 +467,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;WINVER=0x0500;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
@ -480,8 +484,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;iphlpapi.lib;PocoFoundation.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>bin64\TestApp.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>
|
||||
</ProgramDatabaseFile>
|
||||
@ -497,7 +502,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;WINVER=0x0500;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
@ -514,8 +519,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ws2_32.lib;iphlpapi.lib;PocoFoundation.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>binA64\TestApp.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\libA64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\libA64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>
|
||||
</ProgramDatabaseFile>
|
||||
@ -531,7 +537,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
@ -548,8 +554,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>PocoFoundationmd.lib;winmm.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>bin\static_md\TestApp.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>
|
||||
</ProgramDatabaseFile>
|
||||
@ -566,7 +573,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
@ -583,8 +590,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>PocoFoundationmd.lib;winmm.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>bin64\static_md\TestApp.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>
|
||||
</ProgramDatabaseFile>
|
||||
@ -600,7 +608,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
@ -617,8 +625,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>PocoFoundationmd.lib;winmm.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>binA64\static_md\TestApp.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\libA64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\libA64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>
|
||||
</ProgramDatabaseFile>
|
||||
@ -630,7 +639,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_md|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
@ -647,8 +656,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>PocoFoundationmdd.lib;winmm.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>bin\static_md\TestAppd.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>bin\static_md\TestAppd.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -658,7 +668,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_md|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
@ -674,8 +684,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>PocoFoundationmdd.lib;winmm.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>bin64\static_md\TestAppd.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>bin64\static_md\TestAppd.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -684,7 +695,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_md|ARM64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
@ -700,8 +711,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>PocoFoundationmdd.lib;winmm.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>binA64\static_md\TestAppd.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\libA64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\libA64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>binA64\static_md\TestAppd.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -710,7 +722,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
@ -727,8 +739,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>PocoFoundationmtd.lib;winmm.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>bin\static_mt\TestAppd.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>bin\static_mt\TestAppd.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -738,7 +751,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|x64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
@ -754,8 +767,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>PocoFoundationmtd.lib;winmm.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>bin64\static_mt\TestAppd.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>bin64\static_mt\TestAppd.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -764,7 +778,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug_static_mt|ARM64'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
@ -780,8 +794,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>PocoFoundationmtd.lib;winmm.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>binA64\static_mt\TestAppd.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\libA64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\libA64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>binA64\static_mt\TestAppd.pdb</ProgramDatabaseFile>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@ -794,7 +809,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
@ -811,8 +826,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>PocoFoundationmt.lib;winmm.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>bin\static_mt\TestApp.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>
|
||||
</ProgramDatabaseFile>
|
||||
@ -829,7 +845,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
@ -846,8 +862,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>PocoFoundationmt.lib;winmm.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>bin64\static_mt\TestApp.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>
|
||||
</ProgramDatabaseFile>
|
||||
@ -863,7 +880,7 @@
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<OmitFramePointers>true</OmitFramePointers>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;WINVER=0x0500;POCO_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
@ -880,8 +897,9 @@
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>PocoFoundationmt.lib;winmm.lib;ws2_32.lib;iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>binA64\static_mt\TestApp.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>..\..\..\libA64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\..\libA64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>
|
||||
</ProgramDatabaseFile>
|
||||
|
@ -985,6 +985,7 @@
|
||||
<ClCompile Include="src\PBKDF2EngineTest.cpp" />
|
||||
<ClCompile Include="src\PriorityEventTest.cpp" />
|
||||
<ClCompile Include="src\PriorityNotificationQueueTest.cpp" />
|
||||
<ClCompile Include="src\ProcessRunnerTest.cpp" />
|
||||
<ClCompile Include="src\ProcessesTestSuite.cpp" />
|
||||
<ClCompile Include="src\ProcessTest.cpp" />
|
||||
<ClCompile Include="src\RandomStreamTest.cpp" />
|
||||
@ -1127,6 +1128,7 @@
|
||||
<ClInclude Include="src\PBKDF2EngineTest.h" />
|
||||
<ClInclude Include="src\PriorityEventTest.h" />
|
||||
<ClInclude Include="src\PriorityNotificationQueueTest.h" />
|
||||
<ClInclude Include="src\ProcessRunnerTest.h" />
|
||||
<ClInclude Include="src\ProcessesTestSuite.h" />
|
||||
<ClInclude Include="src\ProcessTest.h" />
|
||||
<ClInclude Include="src\RandomStreamTest.h" />
|
||||
|
@ -519,6 +519,9 @@
|
||||
<ClCompile Include="src\NamedMutexTest.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ProcessRunnerTest.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ProcessesTestSuite.cpp">
|
||||
<Filter>Processes\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -938,6 +941,9 @@
|
||||
<ClInclude Include="src\NamedMutexTest.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ProcessRunnerTest.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ProcessesTestSuite.h">
|
||||
<Filter>Processes\Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "Poco/Manifest.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Format.h"
|
||||
#include "TestPlugin.h"
|
||||
|
||||
|
||||
@ -24,6 +26,8 @@ using Poco::SharedLibrary;
|
||||
using Poco::AbstractMetaObject;
|
||||
using Poco::NotFoundException;
|
||||
using Poco::InvalidAccessException;
|
||||
using Poco::Path;
|
||||
using Poco::File;
|
||||
|
||||
|
||||
ClassLoaderTest::ClassLoaderTest(const std::string& name): CppUnit::TestCase(name)
|
||||
@ -38,17 +42,14 @@ ClassLoaderTest::~ClassLoaderTest()
|
||||
|
||||
void ClassLoaderTest::testClassLoader1()
|
||||
{
|
||||
std::string path = "TestLibrary";
|
||||
path.append(SharedLibrary::suffix());
|
||||
Poco::Path libraryPath = Poco::Path::current();
|
||||
libraryPath.append(path);
|
||||
std::string libraryPath = getFullName("TestLibrary");
|
||||
ClassLoader<TestPlugin> cl;
|
||||
|
||||
assertTrue (cl.begin() == cl.end());
|
||||
assertNullPtr (cl.findClass("PluginA"));
|
||||
assertNullPtr (cl.findManifest(libraryPath.toString()));
|
||||
assertNullPtr (cl.findManifest(libraryPath));
|
||||
|
||||
assertTrue (!cl.isLibraryLoaded(libraryPath.toString()));
|
||||
assertTrue (!cl.isLibraryLoaded(libraryPath));
|
||||
|
||||
try
|
||||
{
|
||||
@ -65,7 +66,7 @@ void ClassLoaderTest::testClassLoader1()
|
||||
|
||||
try
|
||||
{
|
||||
const ClassLoader<TestPlugin>::Manif& POCO_UNUSED manif = cl.manifestFor(libraryPath.toString());
|
||||
const ClassLoader<TestPlugin>::Manif& POCO_UNUSED manif = cl.manifestFor(libraryPath);
|
||||
fail("not found - must throw exception");
|
||||
}
|
||||
catch (NotFoundException&)
|
||||
@ -80,25 +81,22 @@ void ClassLoaderTest::testClassLoader1()
|
||||
|
||||
void ClassLoaderTest::testClassLoader2()
|
||||
{
|
||||
std::string path = "TestLibrary";
|
||||
path.append(SharedLibrary::suffix());
|
||||
Poco::Path libraryPath = Poco::Path::current();
|
||||
libraryPath.append(path);
|
||||
std::string libraryPath = getFullName("TestLibrary");
|
||||
ClassLoader<TestPlugin> cl;
|
||||
cl.loadLibrary(libraryPath.toString());
|
||||
cl.loadLibrary(libraryPath);
|
||||
|
||||
assertTrue (cl.begin() != cl.end());
|
||||
assertNotNullPtr (cl.findClass("PluginA"));
|
||||
assertNotNullPtr (cl.findClass("PluginB"));
|
||||
assertNotNullPtr (cl.findClass("PluginC"));
|
||||
assertNotNullPtr (cl.findManifest(libraryPath.toString()));
|
||||
assertNotNullPtr (cl.findManifest(libraryPath));
|
||||
|
||||
assertTrue (cl.isLibraryLoaded(libraryPath.toString()));
|
||||
assertTrue (cl.manifestFor(libraryPath.toString()).size() == 3);
|
||||
assertTrue (cl.isLibraryLoaded(libraryPath));
|
||||
assertTrue (cl.manifestFor(libraryPath).size() == 3);
|
||||
|
||||
ClassLoader<TestPlugin>::Iterator it = cl.begin();
|
||||
assertTrue (it != cl.end());
|
||||
assertTrue (it->first == libraryPath.toString());
|
||||
assertTrue (it->first == libraryPath);
|
||||
assertTrue (it->second->size() == 3);
|
||||
++it;
|
||||
assertTrue (it == cl.end());
|
||||
@ -165,32 +163,55 @@ void ClassLoaderTest::testClassLoader2()
|
||||
meta2.destroy(pPlugin);
|
||||
assertTrue (!meta2.isAutoDelete(pPlugin));
|
||||
|
||||
cl.unloadLibrary(libraryPath.toString());
|
||||
cl.unloadLibrary(libraryPath);
|
||||
}
|
||||
|
||||
|
||||
void ClassLoaderTest::testClassLoader3()
|
||||
{
|
||||
std::string path = "TestLibrary";
|
||||
path.append(SharedLibrary::suffix());
|
||||
Poco::Path libraryPath = Poco::Path::current();
|
||||
libraryPath.append(path);
|
||||
std::string libraryPath = getFullName("TestLibrary");
|
||||
ClassLoader<TestPlugin> cl;
|
||||
cl.loadLibrary(libraryPath.toString());
|
||||
cl.loadLibrary(libraryPath.toString());
|
||||
cl.unloadLibrary(libraryPath.toString());
|
||||
cl.loadLibrary(libraryPath);
|
||||
cl.loadLibrary(libraryPath);
|
||||
cl.unloadLibrary(libraryPath);
|
||||
|
||||
assertTrue (cl.manifestFor(libraryPath.toString()).size() == 3);
|
||||
assertTrue (cl.manifestFor(libraryPath).size() == 3);
|
||||
|
||||
ClassLoader<TestPlugin>::Iterator it = cl.begin();
|
||||
assertTrue (it != cl.end());
|
||||
assertTrue (it->first == libraryPath.toString());
|
||||
assertTrue (it->first == libraryPath);
|
||||
assertTrue (it->second->size() == 3);
|
||||
++it;
|
||||
assertTrue (it == cl.end());
|
||||
|
||||
cl.unloadLibrary(libraryPath.toString());
|
||||
assertNullPtr (cl.findManifest(libraryPath.toString()));
|
||||
cl.unloadLibrary(libraryPath);
|
||||
assertNullPtr (cl.findManifest(libraryPath));
|
||||
}
|
||||
|
||||
|
||||
std::string ClassLoaderTest::getFullName(const std::string& libName)
|
||||
{
|
||||
std::string name = Path::expand("$POCO_BASE");
|
||||
char c = Path::separator();
|
||||
std::string OSNAME = Path::expand("$OSNAME");
|
||||
std::string OSARCH = Path::expand("$OSARCH");
|
||||
name.append(1, c)
|
||||
.append(Poco::format("Foundation%ctestsuite%cbin%c", c, c, c))
|
||||
.append(Poco::format("%s%c%s%c", OSNAME, c, OSARCH, c))
|
||||
.append(libName).append(SharedLibrary::suffix());
|
||||
|
||||
// CMake
|
||||
if (!File(name).exists())
|
||||
{
|
||||
name = Path::expand("$POCO_BASE");
|
||||
name.append(Poco::format("%ccmake-build%cbin%c", c, c, c))
|
||||
.append(libName).append(SharedLibrary::suffix());
|
||||
}
|
||||
|
||||
if (!File(name).exists())
|
||||
name = libName + SharedLibrary::suffix();
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,6 +34,7 @@ public:
|
||||
static CppUnit::Test* suite();
|
||||
|
||||
private:
|
||||
static std::string getFullName(const std::string& libName);
|
||||
};
|
||||
|
||||
|
||||
|
348
Foundation/testsuite/src/ProcessRunnerTest.cpp
Normal file
348
Foundation/testsuite/src/ProcessRunnerTest.cpp
Normal file
@ -0,0 +1,348 @@
|
||||
//
|
||||
// ProcessRunnerTest.cpp
|
||||
//
|
||||
// Copyright (c) 2023, Applied Informatics Software Engineering GmbH.
|
||||
// Aleph ONE Software Engineering d.o.o.,
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "ProcessRunnerTest.h"
|
||||
#include "CppUnit/TestCaller.h"
|
||||
#include "CppUnit/TestSuite.h"
|
||||
#include "Poco/PIDFile.h"
|
||||
#include "Poco/Format.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/FileStream.h"
|
||||
|
||||
|
||||
using namespace Poco;
|
||||
|
||||
|
||||
ProcessRunnerTest::ProcessRunnerTest(const std::string& name):
|
||||
CppUnit::TestCase(name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ProcessRunnerTest::~ProcessRunnerTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ProcessRunnerTest::testPIDFile()
|
||||
{
|
||||
std::string pidFile = Path::tempHome() + "test.pid";
|
||||
|
||||
{
|
||||
PIDFile f;
|
||||
assertTrue (f.getName().empty());
|
||||
assertTrue (f.getPID() == PIDFile::INVALID_PID);
|
||||
assertFalse (File(pidFile).exists());
|
||||
|
||||
f.setName(pidFile);
|
||||
assertTrue (f.getName() == pidFile);
|
||||
assertTrue (f.getPID() != PIDFile::INVALID_PID);
|
||||
assertTrue (File(pidFile).exists());
|
||||
}
|
||||
assertFalse (File(pidFile).exists());
|
||||
|
||||
{
|
||||
PIDFile f(pidFile);
|
||||
std::string pf = pidFile;
|
||||
|
||||
assertTrue (f.getName() == pf);
|
||||
assertTrue (File(pf).exists());
|
||||
assertTrue (f.getPID() != PIDFile::INVALID_PID);
|
||||
|
||||
assertTrue (f.exists());
|
||||
}
|
||||
assertFalse (File(pidFile).exists());
|
||||
|
||||
{
|
||||
PIDFile f(pidFile);
|
||||
assertTrue (f.getName() == pidFile);
|
||||
assertTrue (File(pidFile).exists());
|
||||
assertTrue (f.getPID() != PIDFile::INVALID_PID);
|
||||
|
||||
assertTrue (f.exists());
|
||||
}
|
||||
assertFalse (File(pidFile).exists());
|
||||
|
||||
{
|
||||
PIDFile f(pidFile, false);
|
||||
std::string pf = pidFile;
|
||||
|
||||
assertTrue (f.getName() == pf);
|
||||
assertTrue (!File(pf).exists());
|
||||
assertTrue (f.getPID() == PIDFile::INVALID_PID);
|
||||
|
||||
f.create();
|
||||
assertTrue (f.exists());
|
||||
}
|
||||
assertFalse (File(pidFile).exists());
|
||||
}
|
||||
|
||||
|
||||
void ProcessRunnerTest::testProcessRunner()
|
||||
{
|
||||
std::string name("TestApp");
|
||||
std::string cmd;
|
||||
#if defined(_DEBUG) && (POCO_OS != POCO_OS_ANDROID)
|
||||
name += "d";
|
||||
#endif
|
||||
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
cmd += name;
|
||||
#elif defined(_WIN32_WCE)
|
||||
cmd = "\\";
|
||||
cmd += name;
|
||||
cmd += ".EXE";
|
||||
#else
|
||||
cmd = name;
|
||||
#endif
|
||||
|
||||
// non-auto start, no PID
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
char c = Path::separator();
|
||||
std::string pidFile = Poco::format("run%c%s.pid", c, name);
|
||||
args.push_back(std::string("--pidfile=").append(pidFile));
|
||||
ProcessRunner pr(cmd, args, "", ProcessRunner::NO_OUT, 10, false);
|
||||
assertTrue (pr.cmdLine() == cmdLine(cmd, args));
|
||||
assertFalse (pr.running());
|
||||
pr.start();
|
||||
|
||||
Stopwatch sw; sw.start();
|
||||
while (!pr.running())
|
||||
checkTimeout(sw, "Waiting for process to start", 1000, __LINE__);
|
||||
|
||||
assertTrue (pr.running());
|
||||
try
|
||||
{
|
||||
pr.start();
|
||||
fail("It should not be possible to start a started process.");
|
||||
}
|
||||
catch(const Poco::InvalidAccessException&) {}
|
||||
pr.stop();
|
||||
sw.restart();
|
||||
while (pr.running())
|
||||
checkTimeout(sw, "Waiting for process to stop", 1000, __LINE__);
|
||||
assertFalse (pr.running());
|
||||
pr.start();
|
||||
while (!pr.running())
|
||||
checkTimeout(sw, "Waiting for process to start", 1000, __LINE__);
|
||||
assertTrue (pr.running());
|
||||
pr.stop();
|
||||
pr.stop(); // second stop() should be silent no-op
|
||||
}
|
||||
|
||||
// non-auto start with PID
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
char c = Path::separator();
|
||||
std::string pidFile = Poco::format("run%c%s.pid", c, name);
|
||||
args.push_back(std::string("--pidfile=").append(pidFile));
|
||||
ProcessRunner pr(cmd, args, "", ProcessRunner::NO_OUT, 10, false);
|
||||
assertTrue (pr.cmdLine() == cmdLine(cmd, args));
|
||||
assertFalse (pr.running());
|
||||
pr.start();
|
||||
Stopwatch sw; sw.start();
|
||||
while (!pr.running())
|
||||
checkTimeout(sw, "Waiting for process to start", 1000, __LINE__);
|
||||
assertTrue (pr.running());
|
||||
try
|
||||
{
|
||||
pr.start();
|
||||
fail("It should not be possible to start a started process.");
|
||||
}
|
||||
catch(const Poco::InvalidAccessException&) {}
|
||||
pr.stop();
|
||||
sw.restart();
|
||||
while (pr.running())
|
||||
checkTimeout(sw, "Waiting for process to stop", 1000, __LINE__);
|
||||
assertFalse (pr.running());
|
||||
pr.start();
|
||||
while (!pr.running())
|
||||
checkTimeout(sw, "Waiting for process to start", 1000, __LINE__);
|
||||
assertTrue (pr.running());
|
||||
pr.stop();
|
||||
pr.stop(); // second stop() should be silent no-op
|
||||
}
|
||||
|
||||
// autodetect PID file from the long command line argument
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
char c = Path::separator();
|
||||
std::string pidFile = Poco::format("run%c%s.pid", c, name);
|
||||
args.push_back(std::string("--pidfile=").append(pidFile));
|
||||
{
|
||||
ProcessRunner pr(cmd, args);
|
||||
assertTrue (pr.cmdLine() == cmdLine(cmd, args));
|
||||
assertTrue (pr.pidFile() == PIDFile::getFileName(pidFile));
|
||||
assertTrue (File(pidFile).exists());
|
||||
assertTrue (PIDFile::contains(pidFile, pr.pid()));
|
||||
}
|
||||
assertTrue (!File(pidFile).exists());
|
||||
}
|
||||
|
||||
// autodetect PID file from the short command line argument
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
char c = Path::separator();
|
||||
std::string pidFile = Poco::format("run%c%s.pid", c, name);
|
||||
args.push_back(std::string("-p=").append(pidFile));
|
||||
{
|
||||
ProcessRunner pr(cmd, args, PIDFile::getFileName(pidFile));
|
||||
assertTrue (pr.cmdLine() == cmdLine(cmd, args));
|
||||
assertTrue (pr.pidFile() == pidFile);
|
||||
assertTrue (File(pidFile).exists());
|
||||
assertTrue (PIDFile::contains(pidFile, pr.pid()));
|
||||
}
|
||||
assertTrue (!File(pidFile).exists());
|
||||
}
|
||||
|
||||
// ProcessRunner should NOT autodetect PID from command line args
|
||||
// if argument formats list is empty
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
char c = Path::separator();
|
||||
std::string pidFile = Poco::format("run%c%s.pid", c, name);
|
||||
args.push_back(std::string("--pidfile=").append(pidFile));
|
||||
{
|
||||
ProcessRunner pr(cmd, args, "", ProcessRunner::NO_OUT, 10, true, {});
|
||||
assertTrue (pr.cmdLine() == cmdLine(cmd, args));
|
||||
assertTrue (pr.pidFile().empty()); // ProcessRunner has no PID file
|
||||
|
||||
PIDFile::getFileName(pidFile);
|
||||
Stopwatch sw; sw.start();
|
||||
while (!File(pidFile).exists())
|
||||
checkTimeout(sw, "Waiting for PID file", 1000, __LINE__);
|
||||
|
||||
// PID file exists and is valid
|
||||
assertTrue (File(pidFile).exists());
|
||||
assertTrue (PIDFile::contains(pidFile, pr.pid()));
|
||||
}
|
||||
assertTrue (!File(pidFile).exists());
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
char c = Path::separator();
|
||||
std::string pidFile = Poco::format("run%c%s.pid", c, name);
|
||||
args.push_back(std::string("-p=").append(pidFile));
|
||||
{
|
||||
ProcessRunner pr(cmd, args, "", ProcessRunner::NO_OUT, 10, true, {});
|
||||
assertTrue (pr.cmdLine() == cmdLine(cmd, args));
|
||||
assertTrue (pr.pidFile().empty()); // ProcessRunner has no PID file
|
||||
|
||||
PIDFile::getFileName(pidFile);
|
||||
Stopwatch sw; sw.start();
|
||||
while (!File(pidFile).exists())
|
||||
checkTimeout(sw, "Waiting for PID file", 1000, __LINE__);
|
||||
|
||||
// PID file exists and is valid
|
||||
assertTrue (File(pidFile).exists());
|
||||
assertTrue (PIDFile::contains(pidFile, pr.pid()));
|
||||
}
|
||||
assertTrue (!File(pidFile).exists());
|
||||
}
|
||||
|
||||
// no PID file created at all
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
char c = Path::separator();
|
||||
std::string pidFile = Poco::format("run%c%s.pid", c, name);
|
||||
{
|
||||
ProcessRunner pr(cmd, args);
|
||||
assertTrue (pr.cmdLine() == cmdLine(cmd, args));
|
||||
assertTrue (pr.pidFile().empty());
|
||||
|
||||
Thread::sleep(500);
|
||||
|
||||
assertTrue (!File(pidFile).exists());
|
||||
assertTrue (!PIDFile::contains(pidFile, pr.pid()));
|
||||
}
|
||||
assertTrue (!File(pidFile).exists());
|
||||
}
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
// start process launching multiple threads
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
char c = Path::separator();
|
||||
std::string pidFile = Poco::format("run%c%s.pid", c, name);
|
||||
args.push_back(std::string("--pidfile=").append(pidFile));
|
||||
args.push_back(std::string("--launch-thread"));
|
||||
ProcessRunner pr(cmd, args, "", ProcessRunner::NO_OUT, 10, false);
|
||||
assertTrue (pr.cmdLine() == cmdLine(cmd, args));
|
||||
assertFalse (pr.running());
|
||||
pr.start();
|
||||
Stopwatch sw; sw.start();
|
||||
while (!pr.running())
|
||||
checkTimeout(sw, "Waiting for process to start", 1000, __LINE__);
|
||||
assertTrue (pr.running());
|
||||
try
|
||||
{
|
||||
pr.start();
|
||||
fail("It should not be possible to start a started process.");
|
||||
}
|
||||
catch(const Poco::InvalidAccessException&) {}
|
||||
pr.stop();
|
||||
sw.restart();
|
||||
while (pr.running())
|
||||
checkTimeout(sw, "Waiting for process to stop", 1000, __LINE__);
|
||||
assertFalse (pr.running());
|
||||
assertEqual (pr.result(), 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
std::string ProcessRunnerTest::cmdLine(const std::string& cmd, const ProcessRunner::Args& args)
|
||||
{
|
||||
std::string cmdL = cmd + ' ';
|
||||
auto it = args.begin();
|
||||
auto end = args.end();
|
||||
for (; it != end;)
|
||||
{
|
||||
cmdL.append(*it);
|
||||
if (++it == end) break;
|
||||
cmdL.append(1, ' ');
|
||||
}
|
||||
return cmdL;
|
||||
}
|
||||
|
||||
|
||||
void ProcessRunnerTest::checkTimeout(const Stopwatch& sw, const std::string& msg, int timeoutMS, int line)
|
||||
{
|
||||
if (sw.elapsedSeconds()*1000 > timeoutMS)
|
||||
{
|
||||
throw Poco::TimeoutException(
|
||||
Poco::format("ProcessRunner::checkTimeout(): %s, line: %d", msg, line));
|
||||
}
|
||||
Thread::sleep(10);
|
||||
}
|
||||
|
||||
|
||||
void ProcessRunnerTest::setUp()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ProcessRunnerTest::tearDown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CppUnit::Test* ProcessRunnerTest::suite()
|
||||
{
|
||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ProcessRunnerTest");
|
||||
|
||||
CppUnit_addTest(pSuite, ProcessRunnerTest, testPIDFile);
|
||||
CppUnit_addTest(pSuite, ProcessRunnerTest, testProcessRunner);
|
||||
|
||||
return pSuite;
|
||||
}
|
44
Foundation/testsuite/src/ProcessRunnerTest.h
Normal file
44
Foundation/testsuite/src/ProcessRunnerTest.h
Normal file
@ -0,0 +1,44 @@
|
||||
//
|
||||
// ProcessRunnerTest.h
|
||||
//
|
||||
// Definition of the ProcessRunnerTest 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 ProcessRunnerTest_INCLUDED
|
||||
#define ProcessRunnerTest_INCLUDED
|
||||
|
||||
|
||||
#include "CppUnit/TestCase.h"
|
||||
#include "Poco/ProcessRunner.h"
|
||||
#include "Poco/Stopwatch.h"
|
||||
|
||||
|
||||
class ProcessRunnerTest: public CppUnit::TestCase
|
||||
{
|
||||
public:
|
||||
ProcessRunnerTest(const std::string& name);
|
||||
~ProcessRunnerTest();
|
||||
|
||||
void testPIDFile();
|
||||
void testProcessRunner();
|
||||
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
static CppUnit::Test* suite();
|
||||
|
||||
private:
|
||||
std::string cmdLine(const std::string& cmd, const Poco::ProcessRunner::Args& args);
|
||||
void checkTimeout(const Poco::Stopwatch& sw, const std::string& msg, int timeoutMS, int line);
|
||||
};
|
||||
|
||||
|
||||
#endif // ProcessRunnerTest_INCLUDED
|
@ -14,12 +14,15 @@
|
||||
#include "Poco/Process.h"
|
||||
#include "Poco/Pipe.h"
|
||||
#include "Poco/PipeStream.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/Format.h"
|
||||
|
||||
|
||||
using namespace std::string_literals;
|
||||
using Poco::Process;
|
||||
using Poco::ProcessHandle;
|
||||
using Poco::Pipe;
|
||||
using Poco::Path;
|
||||
using Poco::PipeInputStream;
|
||||
using Poco::PipeOutputStream;
|
||||
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
static CppUnit::Test* suite();
|
||||
|
||||
private:
|
||||
static std::string getFullName(const std::string& name);
|
||||
};
|
||||
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "NamedMutexTest.h"
|
||||
#include "NamedEventTest.h"
|
||||
#include "SharedMemoryTest.h"
|
||||
#include "ProcessRunnerTest.h"
|
||||
|
||||
|
||||
CppUnit::Test* ProcessesTestSuite::suite()
|
||||
@ -23,6 +24,7 @@ CppUnit::Test* ProcessesTestSuite::suite()
|
||||
pSuite->addTest(NamedMutexTest::suite());
|
||||
pSuite->addTest(NamedEventTest::suite());
|
||||
pSuite->addTest(SharedMemoryTest::suite());
|
||||
pSuite->addTest(ProcessRunnerTest::suite());
|
||||
|
||||
return pSuite;
|
||||
}
|
||||
|
@ -14,12 +14,16 @@
|
||||
#include "Poco/SharedLibrary.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Format.h"
|
||||
|
||||
|
||||
using Poco::SharedLibrary;
|
||||
using Poco::NotFoundException;
|
||||
using Poco::LibraryLoadException;
|
||||
using Poco::LibraryAlreadyLoadedException;
|
||||
using Poco::Path;
|
||||
using Poco::File;
|
||||
|
||||
|
||||
typedef int (*GimmeFiveFunc)();
|
||||
@ -37,14 +41,11 @@ SharedLibraryTest::~SharedLibraryTest()
|
||||
|
||||
void SharedLibraryTest::testSharedLibrary1()
|
||||
{
|
||||
std::string path = "TestLibrary";
|
||||
path.append(SharedLibrary::suffix());
|
||||
Poco::Path libraryPath = Poco::Path::current();
|
||||
libraryPath.append(path);
|
||||
std::string libraryPath = getFullName("TestLibrary");
|
||||
SharedLibrary sl;
|
||||
assertTrue (!sl.isLoaded());
|
||||
sl.load(libraryPath.toString());
|
||||
assertTrue (sl.getPath() == libraryPath.toString());
|
||||
sl.load(libraryPath);
|
||||
assertTrue (sl.getPath() == libraryPath);
|
||||
assertTrue (sl.isLoaded());
|
||||
assertTrue (sl.hasSymbol("pocoBuildManifest"));
|
||||
assertTrue (sl.hasSymbol("pocoInitializeLibrary"));
|
||||
@ -73,12 +74,9 @@ void SharedLibraryTest::testSharedLibrary1()
|
||||
|
||||
void SharedLibraryTest::testSharedLibrary2()
|
||||
{
|
||||
std::string path = "TestLibrary";
|
||||
path.append(SharedLibrary::suffix());
|
||||
Poco::Path libraryPath = Poco::Path::current();
|
||||
libraryPath.append(path);
|
||||
SharedLibrary sl(libraryPath.toString());
|
||||
assertTrue (sl.getPath() == libraryPath.toString());
|
||||
std::string libraryPath = getFullName("TestLibrary");
|
||||
SharedLibrary sl(libraryPath);
|
||||
assertTrue (sl.getPath() == libraryPath);
|
||||
assertTrue (sl.isLoaded());
|
||||
|
||||
GimmeFiveFunc gimmeFive = (GimmeFiveFunc) sl.getSymbol("gimmeFive");
|
||||
@ -91,12 +89,12 @@ void SharedLibraryTest::testSharedLibrary2()
|
||||
|
||||
void SharedLibraryTest::testSharedLibrary3()
|
||||
{
|
||||
std::string path = "NonexistentLibrary";
|
||||
path.append(SharedLibrary::suffix());
|
||||
std::string libraryPath = "NonexistentLibrary";
|
||||
libraryPath.append(libraryPath);
|
||||
SharedLibrary sl;
|
||||
try
|
||||
{
|
||||
sl.load(path);
|
||||
sl.load(libraryPath);
|
||||
failmsg("no such library - must throw exception");
|
||||
}
|
||||
catch (LibraryLoadException&)
|
||||
@ -108,16 +106,13 @@ void SharedLibraryTest::testSharedLibrary3()
|
||||
}
|
||||
assertTrue (!sl.isLoaded());
|
||||
|
||||
path = "TestLibrary";
|
||||
path.append(SharedLibrary::suffix());
|
||||
Poco::Path libraryPath = Poco::Path::current();
|
||||
libraryPath.append(path);
|
||||
sl.load(libraryPath.toString());
|
||||
libraryPath = getFullName("TestLibrary");
|
||||
sl.load(libraryPath);
|
||||
assertTrue (sl.isLoaded());
|
||||
|
||||
try
|
||||
{
|
||||
sl.load(libraryPath.toString());
|
||||
sl.load(libraryPath);
|
||||
failmsg("library already loaded - must throw exception");
|
||||
}
|
||||
catch (LibraryAlreadyLoadedException&)
|
||||
@ -134,6 +129,33 @@ void SharedLibraryTest::testSharedLibrary3()
|
||||
}
|
||||
|
||||
|
||||
std::string SharedLibraryTest::getFullName(const std::string& libName)
|
||||
{
|
||||
// make
|
||||
std::string name = Path::expand("$POCO_BASE");
|
||||
char c = Path::separator();
|
||||
std::string OSNAME = Path::expand("$OSNAME");
|
||||
std::string OSARCH = Path::expand("$OSARCH");
|
||||
name.append(1, c)
|
||||
.append(Poco::format("Foundation%ctestsuite%cbin%c", c, c, c))
|
||||
.append(Poco::format("%s%c%s%c", OSNAME, c, OSARCH, c))
|
||||
.append(libName).append(SharedLibrary::suffix());
|
||||
|
||||
// CMake
|
||||
if (!File(name).exists())
|
||||
{
|
||||
name = Path::expand("$POCO_BASE");
|
||||
name.append(Poco::format("%ccmake-build%cbin%c", c, c, c))
|
||||
.append(libName).append(SharedLibrary::suffix());
|
||||
}
|
||||
|
||||
if (!File(name).exists())
|
||||
name = libName + SharedLibrary::suffix();
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
void SharedLibraryTest::setUp()
|
||||
{
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ public:
|
||||
static CppUnit::Test* suite();
|
||||
|
||||
private:
|
||||
static std::string getFullName(const std::string& libName);
|
||||
};
|
||||
|
||||
|
||||
|
@ -12,12 +12,151 @@
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#endif
|
||||
|
||||
#include "Poco/PIDFile.h"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <signal.h>
|
||||
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
#include "Poco/Thread.h"
|
||||
#include "Poco/Runnable.h"
|
||||
#elif defined(POCO_OS_FAMILY_WINDOWS)
|
||||
#include "Poco/Process.h"
|
||||
#include "Poco/Event.h"
|
||||
#include "Poco/NamedEvent.h"
|
||||
#endif
|
||||
|
||||
using namespace Poco;
|
||||
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
class MyRunnable: public Runnable
|
||||
{
|
||||
public:
|
||||
MyRunnable(): _ran(false)
|
||||
{
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
Thread* pThread = Thread::current();
|
||||
if (pThread)
|
||||
{
|
||||
_threadName = pThread->name();
|
||||
}
|
||||
_ran = true;
|
||||
}
|
||||
|
||||
bool ran() const
|
||||
{
|
||||
return _ran;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _ran;
|
||||
std::string _threadName;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if POCO_OS != POCO_OS_ANDROID
|
||||
class MyApp
|
||||
{
|
||||
public:
|
||||
MyApp() {}
|
||||
~MyApp() {}
|
||||
|
||||
std::unique_ptr<PIDFile> _pPIDFile;
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
static Poco::Event _terminated;
|
||||
static Poco::NamedEvent _terminate;
|
||||
|
||||
|
||||
static void terminate()
|
||||
{
|
||||
_terminate.set();
|
||||
}
|
||||
|
||||
|
||||
static BOOL WINAPI ConsoleCtrlHandler(DWORD ctrlType)
|
||||
{
|
||||
switch (ctrlType)
|
||||
{
|
||||
case CTRL_C_EVENT:
|
||||
case CTRL_CLOSE_EVENT:
|
||||
case CTRL_BREAK_EVENT:
|
||||
terminate();
|
||||
return _terminated.tryWait(10000) ? TRUE : FALSE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void waitForTerminationRequest()
|
||||
{
|
||||
SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
|
||||
_terminate.wait();
|
||||
_terminated.set();
|
||||
}
|
||||
#elif defined(POCO_OS_FAMILY_UNIX)
|
||||
void waitForTerminationRequest()
|
||||
{
|
||||
sigset_t sset;
|
||||
sigemptyset(&sset);
|
||||
if (!std::getenv("POCO_ENABLE_DEBUGGER"))
|
||||
{
|
||||
sigaddset(&sset, SIGINT);
|
||||
}
|
||||
sigaddset(&sset, SIGQUIT);
|
||||
sigaddset(&sset, SIGTERM);
|
||||
sigprocmask(SIG_BLOCK, &sset, NULL);
|
||||
int sig;
|
||||
sigwait(&sset, &sig);
|
||||
}
|
||||
|
||||
int runThreads(std::string pidPath)
|
||||
{
|
||||
_pPIDFile.reset(new PIDFile(pidPath, true));
|
||||
|
||||
uint32_t sigMask = 4; // Block SIGINT
|
||||
|
||||
Thread thread1(sigMask);
|
||||
Thread thread2(sigMask);
|
||||
Thread thread3(sigMask);
|
||||
Thread thread4(sigMask);
|
||||
|
||||
MyRunnable r1;
|
||||
MyRunnable r2;
|
||||
MyRunnable r3;
|
||||
MyRunnable r4;
|
||||
|
||||
thread1.start(r1);
|
||||
thread2.start(r2);
|
||||
thread3.start(r3);
|
||||
thread4.start(r4);
|
||||
|
||||
waitForTerminationRequest();
|
||||
|
||||
thread1.join();
|
||||
thread2.join();
|
||||
thread3.join();
|
||||
thread4.join();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int run(std::string pidPath)
|
||||
{
|
||||
_pPIDFile.reset(new PIDFile(pidPath, true));
|
||||
waitForTerminationRequest();
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#if defined(POCO_OS_FAMILY_WINDOWS)
|
||||
Poco::Event MyApp::_terminated;
|
||||
Poco::NamedEvent MyApp::_terminate(Poco::ProcessImpl::terminationEventName(Poco::Process::id()));
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
@ -57,6 +196,32 @@ int main(int argc, char** argv)
|
||||
std::cout << argv[i] << std::endl;
|
||||
}
|
||||
}
|
||||
#if defined(POCO_OS_FAMILY_UNIX)
|
||||
else if (argc > 2 && arg.find("--pidfile") != std::string::npos && std::string(argv[2]) == "--launch-thread")
|
||||
{
|
||||
size_t equals_pos = arg.find('=');
|
||||
if (equals_pos != std::string::npos)
|
||||
{
|
||||
std::string pidPath = arg.substr(equals_pos + 1);
|
||||
MyApp myApp;
|
||||
int result = myApp.runThreads(pidPath);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if POCO_OS != POCO_OS_ANDROID
|
||||
else if (arg.find("--pidfile") != std::string::npos || arg.find("-p") != std::string::npos)
|
||||
{
|
||||
size_t equals_pos = arg.find('=');
|
||||
if (equals_pos != std::string::npos)
|
||||
{
|
||||
std::string pidPath = arg.substr(equals_pos + 1);
|
||||
MyApp myApp;
|
||||
int result = myApp.run(pidPath);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return argc - 1;
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ do
|
||||
echo ""
|
||||
|
||||
runs=$((runs + 1))
|
||||
if ! sh -c "cd $POCO_BUILD/$comp/testsuite/$BINDIR && PATH=.:$PATH && LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH $TESTRUNNER $IGNORE $TESTRUNNERARGS";
|
||||
if ! sh -c "export POCO_BASE='$POCO_BASE'; export OSNAME='$OSNAME'; export OSARCH='$OSARCH'; cd $POCO_BUILD/$comp/testsuite/$BINDIR && PATH=.:$PATH && LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH $TESTRUNNER $IGNORE $TESTRUNNERARGS";
|
||||
then
|
||||
failures=$((failures + 1))
|
||||
failedTests="$failedTests $comp"
|
||||
|
@ -93,6 +93,8 @@ esac
|
||||
# uncomment for sanitizer builds
|
||||
#LSAN_OPTIONS=verbosity=1:log_threads=1
|
||||
#export LSAN_OPTIONS
|
||||
#TSAN_OPTIONS="suppressions=$POCO_BASE/tsan.suppress,second_deadlock_stack=1"
|
||||
#export TSAN_OPTIONS
|
||||
|
||||
echo "\$OSNAME = $OSNAME"
|
||||
echo "\$OSARCH = $OSARCH"
|
||||
|
@ -3,7 +3,7 @@
|
||||
# https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions
|
||||
#
|
||||
# To apply:
|
||||
# export TSAN_OPTIONS="suppressions=$POCO_BASE/tsan.supress,second_deadlock_stack=1"
|
||||
# export TSAN_OPTIONS="suppressions=$POCO_BASE/tsan.suppress,second_deadlock_stack=1"
|
||||
|
||||
##############
|
||||
# Suppressions:
|
||||
|
Loading…
Reference in New Issue
Block a user