summaryrefslogtreecommitdiff
path: root/graphics/asymptote/LspCpp/src/lsp/ParentProcessWatcher.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/asymptote/LspCpp/src/lsp/ParentProcessWatcher.cpp')
-rwxr-xr-xgraphics/asymptote/LspCpp/src/lsp/ParentProcessWatcher.cpp106
1 files changed, 106 insertions, 0 deletions
diff --git a/graphics/asymptote/LspCpp/src/lsp/ParentProcessWatcher.cpp b/graphics/asymptote/LspCpp/src/lsp/ParentProcessWatcher.cpp
new file mode 100755
index 0000000000..57adb7e497
--- /dev/null
+++ b/graphics/asymptote/LspCpp/src/lsp/ParentProcessWatcher.cpp
@@ -0,0 +1,106 @@
+#include "LibLsp/lsp/ParentProcessWatcher.h"
+#include <boost/process.hpp>
+
+#ifdef _WIN32
+#include <boost/process/windows.hpp>
+#endif
+
+#include <boost/filesystem.hpp>
+#include <boost/asio.hpp>
+#include <iostream>
+
+#include "LibLsp/lsp/ProcessIoService.h"
+#include "LibLsp/lsp/SimpleTimer.h"
+
+
+using namespace boost::asio::ip;
+using namespace std;
+
+struct ParentProcessWatcher::ParentProcessWatcherData : std::enable_shared_from_this<ParentProcessWatcherData>
+{
+ std::unique_ptr<SimpleTimer<boost::posix_time::seconds>> timer;
+ lsp::Log& _log;
+ std::function<void()> on_exit;
+ lsp::ProcessIoService asio_io;
+ std::shared_ptr < boost::process::opstream> write_to_service;
+ std::shared_ptr< boost::process::ipstream > read_from_service;
+ int pid;
+ const int _poll_delay_secs /*= 10*/;
+ std::string command;
+ std::shared_ptr<boost::process::child> c;
+
+ ParentProcessWatcherData(lsp::Log& log, int _pid,
+ const std::function<void()>&& callback, uint32_t poll_delay_secs) :
+ _log(log), on_exit(callback), pid(_pid), _poll_delay_secs(poll_delay_secs)
+ {
+#ifdef _WIN32
+ command = "cmd /c \"tasklist /FI \"PID eq " + std::to_string(pid) + "\" | findstr " +
+ std::to_string(pid) + "\"";
+#else
+ command = "ps -p " + std::to_string(pid);
+#endif
+
+ }
+
+ void run()
+ {
+ write_to_service = std::make_shared<boost::process::opstream>();
+ read_from_service = std::make_shared<boost::process::ipstream>();
+
+// const uint32_t POLL_DELAY_SECS = _poll_delay_secs;
+ auto self(shared_from_this());
+ std::error_code ec;
+ namespace bp = boost::process;
+ c = std::make_shared<bp::child>(asio_io.getIOService(), command,
+ ec,
+#ifdef _WIN32
+ bp::windows::hide,
+#endif
+ bp::std_out > *read_from_service,
+ bp::std_in < *write_to_service,
+ bp::on_exit([self](int exit_code, const std::error_code& ec_in) {
+ // the tasklist command should return 0 (parent process exists) or 1 (parent process doesn't exist)
+ if (exit_code == 1)//
+ {
+ if (self->on_exit)
+ {
+
+ std::thread([=]()
+ {
+ std::this_thread::sleep_for(std::chrono::seconds(3));
+ self->on_exit();
+ }).detach();
+ }
+ }
+ else
+ {
+ if (exit_code > 1)
+ {
+ self->_log.log(lsp::Log::Level::WARNING, "The tasklist command: '" + self->command + "' returns " + std::to_string(exit_code));
+ }
+
+ self->timer = std::make_unique<SimpleTimer<boost::posix_time::seconds>>(self->_poll_delay_secs, [=]() {
+ self->run();
+ });
+ }
+
+ }));
+ if (ec)
+ {
+ // fail
+ _log.log(lsp::Log::Level::SEVERE, "Start parent process watcher failed.");
+ }
+ }
+};
+
+ParentProcessWatcher::ParentProcessWatcher(lsp::Log& log, int pid,
+ const std::function<void()>&& callback, uint32_t poll_delay_secs) : d_ptr(new ParentProcessWatcherData(log, pid, std::move(callback), poll_delay_secs))
+{
+ d_ptr->run();
+}
+
+ParentProcessWatcher::~ParentProcessWatcher()
+{
+ if (d_ptr->timer)
+ d_ptr->timer->Stop();
+}