chore: WlClipboard remove unused process control methods
This commit is contained in:
parent
4ebf5ff479
commit
50fd3365e8
2 changed files with 0 additions and 240 deletions
|
|
@ -10,12 +10,8 @@
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <common/Settings.h>
|
#include <common/Settings.h>
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <spawn.h>
|
#include <spawn.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
@ -49,123 +45,6 @@ const int kCommandTimeout = 5000;
|
||||||
const int kCacheValidityMs = 100;
|
const int kCacheValidityMs = 100;
|
||||||
const int kMonitorIntervalMs = 1000;
|
const int kMonitorIntervalMs = 1000;
|
||||||
const int kMaxConsecutiveErrors = 5;
|
const int kMaxConsecutiveErrors = 5;
|
||||||
|
|
||||||
// Helper function to wait for process with timeout and proper cleanup
|
|
||||||
bool waitpidWithTimeout(pid_t pid, int *status, int timeout_ms)
|
|
||||||
{
|
|
||||||
auto start = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
int result = waitpid(pid, status, WNOHANG);
|
|
||||||
if (result == pid) {
|
|
||||||
return true; // Process finished
|
|
||||||
} else if (result == -1) {
|
|
||||||
if (errno == EINTR) {
|
|
||||||
continue; // Interrupted, try again
|
|
||||||
}
|
|
||||||
return false; // Error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check timeout
|
|
||||||
auto now = std::chrono::steady_clock::now();
|
|
||||||
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count();
|
|
||||||
if (elapsed >= timeout_ms) {
|
|
||||||
// Timeout - terminate the process
|
|
||||||
kill(pid, SIGTERM);
|
|
||||||
usleep(100000); // Give it 100ms to terminate gracefully
|
|
||||||
|
|
||||||
result = waitpid(pid, status, WNOHANG);
|
|
||||||
if (result != pid) {
|
|
||||||
// Still not dead, force kill
|
|
||||||
kill(pid, SIGKILL);
|
|
||||||
waitpid(pid, status, 0); // This should not block
|
|
||||||
}
|
|
||||||
return false; // Timed out
|
|
||||||
}
|
|
||||||
|
|
||||||
usleep(10000); // Sleep 10ms before checking again
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RAII class for managing processes with exception safety
|
|
||||||
class ProcessGuard
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
pid_t m_pid;
|
|
||||||
bool m_released;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ProcessGuard(pid_t pid) : m_pid(pid), m_released(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~ProcessGuard()
|
|
||||||
{
|
|
||||||
if (!m_released && m_pid > 0) {
|
|
||||||
// Force cleanup if not properly released
|
|
||||||
kill(m_pid, SIGTERM);
|
|
||||||
usleep(100000);
|
|
||||||
kill(m_pid, SIGKILL);
|
|
||||||
int status;
|
|
||||||
waitpid(m_pid, &status, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Non-copyable, non-movable for simplicity
|
|
||||||
ProcessGuard(const ProcessGuard &) = delete;
|
|
||||||
ProcessGuard &operator=(const ProcessGuard &) = delete;
|
|
||||||
ProcessGuard(ProcessGuard &&) = delete;
|
|
||||||
ProcessGuard &operator=(ProcessGuard &&) = delete;
|
|
||||||
|
|
||||||
pid_t get() const
|
|
||||||
{
|
|
||||||
return m_pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
void release()
|
|
||||||
{
|
|
||||||
m_released = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// RAII class for file descriptors
|
|
||||||
class FdGuard
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
int m_fd;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FdGuard(int fd) : m_fd(fd)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~FdGuard()
|
|
||||||
{
|
|
||||||
if (m_fd >= 0) {
|
|
||||||
::close(m_fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Non-copyable, non-movable for simplicity
|
|
||||||
FdGuard(const FdGuard &) = delete;
|
|
||||||
FdGuard &operator=(const FdGuard &) = delete;
|
|
||||||
FdGuard(FdGuard &&) = delete;
|
|
||||||
FdGuard &operator=(FdGuard &&) = delete;
|
|
||||||
|
|
||||||
int get() const
|
|
||||||
{
|
|
||||||
return m_fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
void close()
|
|
||||||
{
|
|
||||||
if (m_fd >= 0) {
|
|
||||||
::close(m_fd);
|
|
||||||
m_fd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
WlClipboard::WlClipboard(ClipboardID id) : m_id(id), m_useClipboard(id == kClipboardClipboard)
|
WlClipboard::WlClipboard(ClipboardID id) : m_id(id), m_useClipboard(id == kClipboardClipboard)
|
||||||
|
|
@ -413,121 +292,6 @@ std::string WlClipboard::get(Format format) const
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WlClipboard::executeCommandWithInput(const std::vector<const char *> &args, const std::string &input) const
|
|
||||||
{
|
|
||||||
int pipefd[2];
|
|
||||||
if (pipe(pipefd) == -1) {
|
|
||||||
LOG_WARN("failed to create pipe");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FdGuard readFd(pipefd[0]);
|
|
||||||
FdGuard writeFd(pipefd[1]);
|
|
||||||
|
|
||||||
// Set FD_CLOEXEC on pipe file descriptors
|
|
||||||
fcntl(readFd.get(), F_SETFD, FD_CLOEXEC);
|
|
||||||
fcntl(writeFd.get(), F_SETFD, FD_CLOEXEC);
|
|
||||||
|
|
||||||
// Set up file actions for posix_spawn
|
|
||||||
posix_spawn_file_actions_t fileActions;
|
|
||||||
posix_spawn_file_actions_init(&fileActions);
|
|
||||||
|
|
||||||
// Redirect stdin from pipe read end
|
|
||||||
posix_spawn_file_actions_adddup2(&fileActions, readFd.get(), STDIN_FILENO);
|
|
||||||
|
|
||||||
// Redirect stdout and stderr to /dev/null
|
|
||||||
posix_spawn_file_actions_addopen(&fileActions, STDOUT_FILENO, "/dev/null", O_WRONLY, 0);
|
|
||||||
posix_spawn_file_actions_addopen(&fileActions, STDERR_FILENO, "/dev/null", O_WRONLY, 0);
|
|
||||||
|
|
||||||
// Close pipe file descriptors in child
|
|
||||||
posix_spawn_file_actions_addclose(&fileActions, readFd.get());
|
|
||||||
posix_spawn_file_actions_addclose(&fileActions, writeFd.get());
|
|
||||||
|
|
||||||
extern char **environ;
|
|
||||||
pid_t pid;
|
|
||||||
int spawnResult = posix_spawnp(&pid, args[0], &fileActions, nullptr, const_cast<char *const *>(args.data()), environ);
|
|
||||||
|
|
||||||
posix_spawn_file_actions_destroy(&fileActions);
|
|
||||||
|
|
||||||
if (spawnResult != 0) {
|
|
||||||
LOG_WARN("failed to spawn process: %s", strerror(spawnResult));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessGuard processGuard(pid);
|
|
||||||
|
|
||||||
// Parent process - close read end
|
|
||||||
readFd.close();
|
|
||||||
|
|
||||||
bool writeSuccess = true;
|
|
||||||
if (!input.empty()) {
|
|
||||||
// Write with timeout using poll
|
|
||||||
struct pollfd pfd;
|
|
||||||
pfd.fd = writeFd.get();
|
|
||||||
pfd.events = POLLOUT;
|
|
||||||
|
|
||||||
const char *data = input.c_str();
|
|
||||||
size_t totalWritten = 0;
|
|
||||||
size_t dataSize = input.length();
|
|
||||||
auto start = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
while (totalWritten < dataSize) {
|
|
||||||
auto now = std::chrono::steady_clock::now();
|
|
||||||
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count();
|
|
||||||
int remainingTimeout = kCommandTimeout - elapsed;
|
|
||||||
|
|
||||||
if (remainingTimeout <= 0) {
|
|
||||||
writeSuccess = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pollResult = poll(&pfd, 1, remainingTimeout);
|
|
||||||
if (pollResult == 0) {
|
|
||||||
writeSuccess = false;
|
|
||||||
break; // Timeout
|
|
||||||
} else if (pollResult < 0) {
|
|
||||||
if (errno == EINTR) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
writeSuccess = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pfd.revents & POLLOUT) {
|
|
||||||
ssize_t written = write(writeFd.get(), data + totalWritten, dataSize - totalWritten);
|
|
||||||
if (written > 0) {
|
|
||||||
totalWritten += written;
|
|
||||||
} else if (written < 0 && errno != EINTR && errno != EAGAIN) {
|
|
||||||
writeSuccess = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pfd.revents & (POLLHUP | POLLERR)) {
|
|
||||||
writeSuccess = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!writeSuccess) {
|
|
||||||
LOG_WARN("failed to write all input data");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
writeFd.close();
|
|
||||||
|
|
||||||
int status;
|
|
||||||
bool processFinished = waitpidWithTimeout(pid, &status, kCommandTimeout);
|
|
||||||
if (processFinished) {
|
|
||||||
processGuard.release();
|
|
||||||
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
|
|
||||||
} else {
|
|
||||||
LOG_WARN("process did not terminate properly");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString WlClipboard::formatToMimeType(Format format) const
|
QString WlClipboard::formatToMimeType(Format format) const
|
||||||
{
|
{
|
||||||
switch (format) {
|
switch (format) {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
@ -69,9 +68,6 @@ public:
|
||||||
std::string get(Format format) const override;
|
std::string get(Format format) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! Execute a command with input data
|
|
||||||
bool executeCommandWithInput(const std::vector<const char *> &args, const std::string &input) const;
|
|
||||||
|
|
||||||
//! Convert IClipboard format to MIME type
|
//! Convert IClipboard format to MIME type
|
||||||
QString formatToMimeType(Format format) const;
|
QString formatToMimeType(Format format) const;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue