diff --git a/Data/src/sql-parser/src/sqlparser_win.h b/Data/src/sql-parser/src/sqlparser_win.h
index 121f28a71..f7a273f85 100644
--- a/Data/src/sql-parser/src/sqlparser_win.h
+++ b/Data/src/sql-parser/src/sqlparser_win.h
@@ -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
diff --git a/Foundation/Foundation_vs140.vcxproj b/Foundation/Foundation_vs140.vcxproj
index 1ce7d199b..878e178e4 100644
--- a/Foundation/Foundation_vs140.vcxproj
+++ b/Foundation/Foundation_vs140.vcxproj
@@ -1093,6 +1093,7 @@
+
@@ -1168,6 +1169,7 @@
true
true
+
@@ -1655,6 +1657,7 @@
+
@@ -1673,6 +1676,7 @@
+
diff --git a/Foundation/Foundation_vs140.vcxproj.filters b/Foundation/Foundation_vs140.vcxproj.filters
index 319858164..4989d157a 100644
--- a/Foundation/Foundation_vs140.vcxproj.filters
+++ b/Foundation/Foundation_vs140.vcxproj.filters
@@ -642,6 +642,9 @@
Processes\Source Files
+
+ Processes\Source Files
+
Processes\Source Files
@@ -669,6 +672,9 @@
Processes\Source Files
+
+ Processes\Source Files
+
Processes\Source Files
@@ -1514,6 +1520,9 @@
Processes\Header Files
+
+ Processes\Header Files
+
Processes\Header Files
@@ -1541,6 +1550,9 @@
Processes\Header Files
+
+ Processes\Header Files
+
Processes\Header Files
diff --git a/Foundation/Foundation_vs150.vcxproj b/Foundation/Foundation_vs150.vcxproj
index 960d00aba..e48de4e18 100644
--- a/Foundation/Foundation_vs150.vcxproj
+++ b/Foundation/Foundation_vs150.vcxproj
@@ -1093,6 +1093,7 @@
+
@@ -1168,6 +1169,7 @@
true
true
+
@@ -1655,6 +1657,7 @@
+
@@ -1673,6 +1676,7 @@
+
diff --git a/Foundation/Foundation_vs150.vcxproj.filters b/Foundation/Foundation_vs150.vcxproj.filters
index e97e0132c..a8fc29f2d 100644
--- a/Foundation/Foundation_vs150.vcxproj.filters
+++ b/Foundation/Foundation_vs150.vcxproj.filters
@@ -642,6 +642,9 @@
Processes\Source Files
+
+ Processes\Source Files
+
Processes\Source Files
@@ -669,6 +672,9 @@
Processes\Source Files
+
+ Processes\Source Files
+
Processes\Source Files
@@ -1514,6 +1520,9 @@
Processes\Header Files
+
+ Processes\Header Files
+
Processes\Header Files
@@ -1541,6 +1550,9 @@
Processes\Header Files
+
+ Processes\Header Files
+
Processes\Header Files
diff --git a/Foundation/Foundation_vs160.vcxproj b/Foundation/Foundation_vs160.vcxproj
index 99854dff3..791df8391 100644
--- a/Foundation/Foundation_vs160.vcxproj
+++ b/Foundation/Foundation_vs160.vcxproj
@@ -1099,6 +1099,7 @@
+
@@ -1174,6 +1175,7 @@
true
true
+
@@ -1661,6 +1663,7 @@
+
@@ -1679,6 +1682,7 @@
+
diff --git a/Foundation/Foundation_vs160.vcxproj.filters b/Foundation/Foundation_vs160.vcxproj.filters
index 07fcc124b..2698f3fbb 100644
--- a/Foundation/Foundation_vs160.vcxproj.filters
+++ b/Foundation/Foundation_vs160.vcxproj.filters
@@ -642,6 +642,9 @@
Processes\Source Files
+
+ Processes\Source Files
+
Processes\Source Files
@@ -669,6 +672,9 @@
Processes\Source Files
+
+ Processes\Source Files
+
Processes\Source Files
@@ -1514,6 +1520,9 @@
Processes\Header Files
+
+ Processes\Header Files
+
Processes\Header Files
@@ -1541,6 +1550,9 @@
Processes\Header Files
+
+ Processes\Header Files
+
Processes\Header Files
diff --git a/Foundation/Foundation_vs170.vcxproj b/Foundation/Foundation_vs170.vcxproj
index 0eac76c95..f79c42792 100644
--- a/Foundation/Foundation_vs170.vcxproj
+++ b/Foundation/Foundation_vs170.vcxproj
@@ -1550,6 +1550,7 @@
+
@@ -1655,6 +1656,7 @@
true
true
+
@@ -2244,6 +2246,7 @@
+
@@ -2262,6 +2265,7 @@
+
diff --git a/Foundation/Foundation_vs170.vcxproj.filters b/Foundation/Foundation_vs170.vcxproj.filters
index fc8cd62ce..15652e5bd 100644
--- a/Foundation/Foundation_vs170.vcxproj.filters
+++ b/Foundation/Foundation_vs170.vcxproj.filters
@@ -642,6 +642,9 @@
Processes\Source Files
+
+ Processes\Source Files
+
Processes\Source Files
@@ -669,6 +672,9 @@
Processes\Source Files
+
+ Processes\Source Files
+
Processes\Source Files
@@ -1514,6 +1520,9 @@
Processes\Header Files
+
+ Processes\Header Files
+
Processes\Header Files
@@ -1541,6 +1550,9 @@
Processes\Header Files
+
+ Processes\Header Files
+
Processes\Header Files
diff --git a/Foundation/Makefile b/Foundation/Makefile
index 447fa3629..96e0100e5 100644
--- a/Foundation/Makefile
+++ b/Foundation/Makefile
@@ -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 \
diff --git a/Foundation/include/Poco/PIDFile.h b/Foundation/include/Poco/PIDFile.h
new file mode 100644
index 000000000..ba5087086
--- /dev/null
+++ b/Foundation/include/Poco/PIDFile.h
@@ -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
+
+
+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;
+
+ 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
diff --git a/Foundation/include/Poco/ProcessRunner.h b/Foundation/include/Poco/ProcessRunner.h
new file mode 100644
index 000000000..ed2fa9fdf
--- /dev/null
+++ b/Foundation/include/Poco/ProcessRunner.h
@@ -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
+#include
+
+
+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;
+ std::string _pidFile;
+ int _options;
+ int _timeout;
+ std::atomic _pPH;
+ std::atomic _started;
+ std::atomic _rc;
+ std::atomic _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
diff --git a/Foundation/include/Poco/Process_UNIX.h b/Foundation/include/Poco/Process_UNIX.h
index 749ddde1a..101243585 100644
--- a/Foundation/include/Poco/Process_UNIX.h
+++ b/Foundation/include/Poco/Process_UNIX.h
@@ -23,6 +23,7 @@
#include
#include
#include