mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-05 17:52:29 +00:00
Fix background task execution.
This commit is contained in:
@@ -37,6 +37,9 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: ubuntu-base
|
||||
steps:
|
||||
- name: Update Packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get install -y \
|
||||
@@ -75,6 +78,9 @@ jobs:
|
||||
matrix:
|
||||
config_flag: ["--with-xmlrpc-c", "--with-xmlrpc-tinyxml2"]
|
||||
steps:
|
||||
- name: Update Packages
|
||||
run: |
|
||||
sudo apt-get update
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get install -y \
|
||||
|
||||
+33
-22
@@ -38,24 +38,10 @@ ExecFile::execute(const char* file, char* const* argv, int flags) {
|
||||
result = write(m_log_fd, "\n---\n", sizeof("\n---\n"));
|
||||
}
|
||||
|
||||
int pipe_fd[2];
|
||||
|
||||
if ((flags & flag_capture) && pipe(pipe_fd))
|
||||
throw torrent::input_error("ExecFile::execute(...) Pipe creation failed.");
|
||||
|
||||
auto clean_fn = [pipe_fd, flags]() {
|
||||
if (flags & flag_capture) {
|
||||
::close(pipe_fd[0]);
|
||||
::close(pipe_fd[1]);
|
||||
}
|
||||
};
|
||||
|
||||
posix_spawn_file_actions_t actions{};
|
||||
|
||||
if (posix_spawn_file_actions_init(&actions) != 0) {
|
||||
clean_fn();
|
||||
if (posix_spawn_file_actions_init(&actions) != 0)
|
||||
throw torrent::internal_error("ExecFile::execute(...) posix_spawn_file_actions_init failed.");
|
||||
}
|
||||
|
||||
// Handle standard input redirection (/dev/null), posix_spawn_file_actions_addopen handles opening
|
||||
// and dup2 natively
|
||||
@@ -64,6 +50,11 @@ ExecFile::execute(const char* file, char* const* argv, int flags) {
|
||||
posix_spawn_file_actions_addclose(&actions, 0);
|
||||
}
|
||||
|
||||
int pipe_fd[2] = {-1, -1};
|
||||
|
||||
if ((flags & flag_capture) && pipe(pipe_fd))
|
||||
throw torrent::input_error("ExecFile::execute(...) Pipe creation failed.");
|
||||
|
||||
// Handle standard output redirection
|
||||
if (flags & flag_capture) {
|
||||
posix_spawn_file_actions_adddup2(&actions, pipe_fd[1], 1);
|
||||
@@ -88,23 +79,36 @@ ExecFile::execute(const char* file, char* const* argv, int flags) {
|
||||
posix_spawnattr_t attr;
|
||||
posix_spawnattr_init(&attr);
|
||||
|
||||
// If you are using standard close-on-exec (O_CLOEXEC) across rtorrent, posix_spawn honors it
|
||||
// automatically. If you want to explicitly enforce a clean slate, modern systems support
|
||||
// POSIX_SPAWN_CLOEXEC_DEFAULT.
|
||||
short spawn_flags = 0;
|
||||
|
||||
#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT
|
||||
posix_spawnattr_setflags(&attr, POSIX_SPAWN_CLOEXEC_DEFAULT);
|
||||
spawn_flags |= POSIX_SPAWN_CLOEXEC_DEFAULT;
|
||||
#endif
|
||||
|
||||
pid_t child_pid{};
|
||||
if (flags & flag_background) {
|
||||
#ifdef POSIX_SPAWN_SETSID
|
||||
spawn_flags |= POSIX_SPAWN_SETSID;
|
||||
#else
|
||||
spawn_flags |= POSIX_SPAWN_SETPGROUP;
|
||||
posix_spawnattr_setpgroup(&attr, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
int spawn_status = posix_spawnp(&child_pid, file, &actions, &attr, argv, environ);
|
||||
posix_spawnattr_setflags(&attr, spawn_flags);
|
||||
|
||||
pid_t child_pid{};
|
||||
int spawn_status = posix_spawnp(&child_pid, file, &actions, &attr, argv, environ);
|
||||
|
||||
posix_spawn_file_actions_destroy(&actions);
|
||||
posix_spawnattr_destroy(&attr);
|
||||
|
||||
if (spawn_status != 0) {
|
||||
clean_fn();
|
||||
if (pipe_fd[0] != -1)
|
||||
::close(pipe_fd[0]);
|
||||
|
||||
if (pipe_fd[1] != -1)
|
||||
::close(pipe_fd[1]);
|
||||
|
||||
throw torrent::input_error("ExecFile::execute(...) posix_spawn failed: " + std::string(std::strerror(spawn_status)));
|
||||
}
|
||||
|
||||
@@ -131,6 +135,13 @@ ExecFile::execute(const char* file, char* const* argv, int flags) {
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & flag_background) {
|
||||
if (m_log_fd != -1)
|
||||
result = write(m_log_fd, "\n--- Running in Background ---\n", sizeof("\n--- Running in Background ---\n"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int status;
|
||||
|
||||
while (waitpid(child_pid, &status, 0) == -1) {
|
||||
|
||||
@@ -81,6 +81,18 @@ SignalHandler::set_unblock(unsigned int signum) {
|
||||
throw std::logic_error("Could not unblock signal: " + std::string(std::strerror(errno)));
|
||||
}
|
||||
|
||||
void
|
||||
SignalHandler::set_sigchild_ignore() {
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sa.sa_flags = SA_NOCLDWAIT | SA_RESTART;
|
||||
|
||||
sigemptyset(&sa.sa_mask);
|
||||
|
||||
if (sigaction(SIGCHLD, &sa, NULL) == -1)
|
||||
throw std::logic_error("Could not set sigaction (ignore) for SIGCHLD: " + std::string(std::strerror(errno)));
|
||||
}
|
||||
|
||||
void
|
||||
SignalHandler::set_sigaction_handler(unsigned int signum, handler_slot slot) {
|
||||
if (signum >= HIGHEST_SIGNAL)
|
||||
|
||||
@@ -25,6 +25,8 @@ public:
|
||||
static void set_block(unsigned int signum);
|
||||
static void set_unblock(unsigned int signum);
|
||||
|
||||
static void set_sigchild_ignore();
|
||||
|
||||
static void set_sigaction_handler(unsigned int signum, handler_slot slot);
|
||||
|
||||
static const char* as_string(unsigned int signum);
|
||||
|
||||
Reference in New Issue
Block a user