From 6d10f56a986945d86cbfc3a6f5a6607cb8457561 Mon Sep 17 00:00:00 2001 From: Horror Proton <107091537+horror-proton@users.noreply.github.com> Date: Wed, 16 Nov 2022 22:17:55 +0800 Subject: [PATCH] feat: add minitouch control for posix --- src/MeoAssistant/Controller.cpp | 104 +++++++++++++++++++++++++++++--- src/MeoAssistant/Controller.h | 4 +- 2 files changed, 99 insertions(+), 9 deletions(-) diff --git a/src/MeoAssistant/Controller.cpp b/src/MeoAssistant/Controller.cpp index e356f7c724..c08cbbe239 100644 --- a/src/MeoAssistant/Controller.cpp +++ b/src/MeoAssistant/Controller.cpp @@ -7,7 +7,11 @@ #include #else #include +#include #include +#ifndef __APPLE__ +#include +#endif #include #include #endif @@ -453,6 +457,12 @@ bool asst::Controller::call_and_hup_minitouch(const std::string& cmd) constexpr int PipeReadBuffSize = 4096ULL; constexpr int PipeWriteBuffSize = 64 * 1024ULL; std::string pipe_str; + + auto check_timeout = [&](const auto& start_time) -> bool { + using namespace std::chrono_literals; + return std::chrono::steady_clock::now() - start_time < 3s; + }; + #ifdef _WIN32 SECURITY_ATTRIBUTES sa_attr_inherit { .nLength = sizeof(SECURITY_ATTRIBUTES), @@ -493,16 +503,12 @@ bool asst::Controller::call_and_hup_minitouch(const std::string& cmd) } auto start_time = std::chrono::steady_clock::now(); - auto check_timeout = [&]() -> bool { - using namespace std::chrono_literals; - return std::chrono::steady_clock::now() - start_time < 3s; - }; auto pipe_buffer = std::make_unique(PipeReadBuffSize); OVERLAPPED pipeov { .hEvent = CreateEventW(nullptr, TRUE, FALSE, nullptr) }; std::ignore = ReadFile(pipe_parent_read, pipe_buffer.get(), PipeReadBuffSize, nullptr, &pipeov); - while (!need_exit() && check_timeout()) { + while (!need_exit() && check_timeout(start_time)) { if (pipe_str.find('$') != std::string::npos) { break; } @@ -518,12 +524,81 @@ bool asst::Controller::call_and_hup_minitouch(const std::string& cmd) pipe_parent_read = INVALID_HANDLE_VALUE; m_minitouch_parent_write = pipe_parent_write; -#else // !_WIN32 +#else // !_WIN32 // TODO + + pid_t pid = 0; + int pipe_to_child[2]; + int pipe_from_child[2]; + + if (::pipe(pipe_to_child)) return false; + if (::pipe(pipe_from_child)) return false; + + pid = fork(); + if (pid < 0) return false; + if (pid == 0) { // child process + if (::dup2(pipe_to_child[0], STDIN_FILENO) < 0 || ::close(pipe_to_child[1]) < 0 || + ::close(pipe_from_child[0]) < 0 || ::dup2(pipe_from_child[1], STDOUT_FILENO) < 0 || + ::dup2(pipe_from_child[1], STDERR_FILENO) < 0) { + ::exit(-1); + } + + // set stdin of child to blocking + if (int val = ::fcntl(STDIN_FILENO, F_GETFL); val != -1 && (val & O_NONBLOCK)) { + val &= ~O_NONBLOCK; + ::fcntl(STDIN_FILENO, F_SETFL, val); + } + +#ifndef __APPLE__ + ::prctl(PR_SET_PDEATHSIG, SIGTERM); +#endif + + ::execlp("/bin/sh", "sh", "-c", cmd.c_str(), nullptr); + exit(-1); + } + + if (::close(pipe_from_child[1]) < 0 || ::close(pipe_to_child[0]) < 0) { + return false; + } + + // set stdout to non blocking + if (int val = ::fcntl(pipe_from_child[0], F_GETFL); val != -1) { + val |= O_NONBLOCK; + ::fcntl(pipe_from_child[0], F_SETFL, val); + } + else + return false; + + const auto start_time = std::chrono::steady_clock::now(); + + // TODO: kill child on fail + + while (true) { + if (need_exit()) return false; + if (!check_timeout(start_time)) { + Log.info("cannot find $ from pipe_str:", Logger::separator::newline, pipe_str); + return false; + } + + if (pipe_str.find('$') != std::string::npos) { + break; + } + + char buf_from_child[PipeReadBuffSize]; + ssize_t ret = ::read(pipe_from_child[0], buf_from_child, PipeReadBuffSize); + if (ret <= 0) continue; + pipe_str.insert(pipe_str.end(), buf_from_child, buf_from_child + ret); + } + + ::dup2(::open("/dev/null", O_WRONLY), pipe_from_child[0]); + + m_minitouch_process = pid; + m_write_to_minitouch_fd = pipe_to_child[1]; + std::ignore = pipe_str; std::ignore = PipeReadBuffSize; std::ignore = PipeWriteBuffSize; - return false; + // return false; #endif // _WIN32 Log.info("pipe str", Logger::separator::newline, pipe_str); @@ -567,6 +642,10 @@ bool asst::Controller::input_to_minitouch(const std::string& cmd) return cmd.size() == written; #else + // TODO + if (m_minitouch_process < 0 || m_write_to_minitouch_fd < 0) return false; + if (::write(m_write_to_minitouch_fd, cmd.c_str(), cmd.length()) >= 0) return true; + Log.error("Failed to write to minitouch, err", errno); return false; #endif } @@ -594,7 +673,16 @@ void asst::Controller::release_minitouch(bool force) CloseHandle(m_minitouch_parent_write); m_minitouch_parent_write = nullptr; } - +#else + if (m_write_to_minitouch_fd != -1) { + ::close(m_write_to_minitouch_fd); + m_write_to_minitouch_fd = -1; + } + if (m_minitouch_process > 0) { + ::kill(m_minitouch_process, SIGTERM); + if (force) ::kill(m_minitouch_process, SIGKILL); + m_minitouch_process = -1; + } #endif // _WIN32 } diff --git a/src/MeoAssistant/Controller.h b/src/MeoAssistant/Controller.h index bf1285b216..209dd4490d 100644 --- a/src/MeoAssistant/Controller.h +++ b/src/MeoAssistant/Controller.h @@ -4,6 +4,7 @@ #include "Utils/Platform/SafeWindows.h" #include #else +#include #include #include #endif @@ -13,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -173,6 +173,8 @@ namespace asst PROCESS_INFORMATION m_minitouch_process_info = { nullptr }; ASST_AUTO_DEDUCED_ZERO_INIT_END #else + ::pid_t m_minitouch_process = -1; + int m_write_to_minitouch_fd = -1; // TODO #endif