Fix background task execution.

This commit is contained in:
Jari Sundell
2026-07-03 10:53:00 +02:00
committed by GitHub
parent 23921cc97c
commit 786f1234d2
4 changed files with 53 additions and 22 deletions
+6
View File
@@ -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
View File
@@ -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) {
+12
View File
@@ -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)
+2
View File
@@ -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);