mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-18 15:16:17 +00:00
Fix background task execution.
This commit is contained in:
@@ -37,6 +37,9 @@ jobs:
|
|||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
needs: ubuntu-base
|
needs: ubuntu-base
|
||||||
steps:
|
steps:
|
||||||
|
- name: Update Packages
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install -y \
|
sudo apt-get install -y \
|
||||||
@@ -75,6 +78,9 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
config_flag: ["--with-xmlrpc-c", "--with-xmlrpc-tinyxml2"]
|
config_flag: ["--with-xmlrpc-c", "--with-xmlrpc-tinyxml2"]
|
||||||
steps:
|
steps:
|
||||||
|
- name: Update Packages
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install -y \
|
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"));
|
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{};
|
posix_spawn_file_actions_t actions{};
|
||||||
|
|
||||||
if (posix_spawn_file_actions_init(&actions) != 0) {
|
if (posix_spawn_file_actions_init(&actions) != 0)
|
||||||
clean_fn();
|
|
||||||
throw torrent::internal_error("ExecFile::execute(...) posix_spawn_file_actions_init failed.");
|
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
|
// Handle standard input redirection (/dev/null), posix_spawn_file_actions_addopen handles opening
|
||||||
// and dup2 natively
|
// and dup2 natively
|
||||||
@@ -64,6 +50,11 @@ ExecFile::execute(const char* file, char* const* argv, int flags) {
|
|||||||
posix_spawn_file_actions_addclose(&actions, 0);
|
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
|
// Handle standard output redirection
|
||||||
if (flags & flag_capture) {
|
if (flags & flag_capture) {
|
||||||
posix_spawn_file_actions_adddup2(&actions, pipe_fd[1], 1);
|
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_t attr;
|
||||||
posix_spawnattr_init(&attr);
|
posix_spawnattr_init(&attr);
|
||||||
|
|
||||||
// If you are using standard close-on-exec (O_CLOEXEC) across rtorrent, posix_spawn honors it
|
short spawn_flags = 0;
|
||||||
// automatically. If you want to explicitly enforce a clean slate, modern systems support
|
|
||||||
// POSIX_SPAWN_CLOEXEC_DEFAULT.
|
|
||||||
|
|
||||||
#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT
|
#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT
|
||||||
posix_spawnattr_setflags(&attr, POSIX_SPAWN_CLOEXEC_DEFAULT);
|
spawn_flags |= POSIX_SPAWN_CLOEXEC_DEFAULT;
|
||||||
#endif
|
#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_spawn_file_actions_destroy(&actions);
|
||||||
posix_spawnattr_destroy(&attr);
|
posix_spawnattr_destroy(&attr);
|
||||||
|
|
||||||
if (spawn_status != 0) {
|
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)));
|
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;
|
int status;
|
||||||
|
|
||||||
while (waitpid(child_pid, &status, 0) == -1) {
|
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)));
|
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
|
void
|
||||||
SignalHandler::set_sigaction_handler(unsigned int signum, handler_slot slot) {
|
SignalHandler::set_sigaction_handler(unsigned int signum, handler_slot slot) {
|
||||||
if (signum >= HIGHEST_SIGNAL)
|
if (signum >= HIGHEST_SIGNAL)
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ public:
|
|||||||
static void set_block(unsigned int signum);
|
static void set_block(unsigned int signum);
|
||||||
static void set_unblock(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 void set_sigaction_handler(unsigned int signum, handler_slot slot);
|
||||||
|
|
||||||
static const char* as_string(unsigned int signum);
|
static const char* as_string(unsigned int signum);
|
||||||
|
|||||||
Reference in New Issue
Block a user