feat: add minitouch control for posix

This commit is contained in:
Horror Proton
2022-11-16 22:17:55 +08:00
parent 842c6a9dac
commit 6d10f56a98
2 changed files with 99 additions and 9 deletions

View File

@@ -7,7 +7,11 @@
#include <ws2tcpip.h>
#else
#include <fcntl.h>
#include <signal.h>
#include <sys/errno.h>
#ifndef __APPLE__
#include <sys/prctl.h>
#endif
#include <sys/wait.h>
#include <unistd.h>
#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<char[]>(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
}