Handle SIGINT/SIGTERM in run_process_foreground for -r
Previously, Ctrl-C or `kill` during -r's bwrap run left slocker_lite killed outright (default signal disposition), skipping run_container()'s unmount/cleanup entirely and leaving the layer imported and/or mounted as garbage. run_process_foreground() now installs a handler around its waitpid() that forwards the signal to the running child (kill(), async-signal- safe) and keeps waiting (EINTR-retry loop) instead of dying. Once the child actually exits, control returns normally so the existing unmount/cleanup runs as usual. Verified with a backgrounded `-r ... -- /bin/sleep 30`, sending both SIGINT and SIGTERM to the outer slocker_lite PID: process tree exits cleanly, unmount+delete-layer both run, containers-storage layers returns to baseline. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -38,7 +38,12 @@ Source layout (all under `src/`):
|
||||
- `process.{h,cpp}` — argv-based subprocess helpers (fork/execvp, no shell):
|
||||
`run_process()` captures stdout (used for `containers-storage` calls),
|
||||
`run_process_foreground()` inherits all of stdio (used for the interactive `bwrap`
|
||||
run). Also `find_in_path()`, a shared `$PATH` lookup.
|
||||
run). Also `find_in_path()`, a shared `$PATH` lookup. `run_process_foreground()`
|
||||
installs a SIGINT/SIGTERM handler around its `waitpid()` that forwards the signal
|
||||
to the running child and keeps waiting instead of letting the default disposition
|
||||
kill `slocker_lite` itself — without this, Ctrl-C (or `kill`) during `-r`'s `bwrap`
|
||||
run would skip `run_container()`'s unmount/cleanup entirely, leaving the layer
|
||||
imported and/or mounted.
|
||||
|
||||
Errors are logged via `spdlog::error`; every external command is also traced at debug
|
||||
level in `run_process()`/`run_process_foreground()` (`src/process.cpp`) — visible via
|
||||
|
||||
+35
-1
@@ -19,6 +19,8 @@
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <csignal>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
@@ -27,6 +29,21 @@
|
||||
|
||||
namespace {
|
||||
|
||||
// Set by run_process_foreground() before it blocks in waitpid(), so the signal
|
||||
// handler below has a pid to forward SIGINT/SIGTERM to (a handler can't take extra
|
||||
// arguments, and this is the conventional way to pass it state).
|
||||
volatile sig_atomic_t g_foreground_child_pid = 0;
|
||||
|
||||
// Forwards the signal to the running foreground child instead of letting the
|
||||
// default disposition kill this process outright -- without this, Ctrl-C or a
|
||||
// `kill` during `-r`'s bwrap run skips run_container()'s unmount/cleanup entirely,
|
||||
// leaving the layer imported and/or mounted. kill() is async-signal-safe.
|
||||
void forward_signal_to_foreground_child(int sig) {
|
||||
if (g_foreground_child_pid > 0) {
|
||||
kill(g_foreground_child_pid, sig);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<char*> to_c_argv(const std::vector<std::string>& argv) {
|
||||
std::vector<char*> c_argv;
|
||||
c_argv.reserve(argv.size() + 1);
|
||||
@@ -107,8 +124,25 @@ int run_process_foreground(const std::vector<std::string>& argv) {
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
g_foreground_child_pid = pid;
|
||||
|
||||
struct sigaction action = {};
|
||||
action.sa_handler = forward_signal_to_foreground_child;
|
||||
sigemptyset(&action.sa_mask);
|
||||
struct sigaction old_sigint;
|
||||
struct sigaction old_sigterm;
|
||||
sigaction(SIGINT, &action, &old_sigint);
|
||||
sigaction(SIGTERM, &action, &old_sigterm);
|
||||
|
||||
int status = 0;
|
||||
waitpid(pid, &status, 0);
|
||||
pid_t wait_result;
|
||||
do {
|
||||
wait_result = waitpid(pid, &status, 0);
|
||||
} while (wait_result == -1 && errno == EINTR);
|
||||
|
||||
sigaction(SIGINT, &old_sigint, nullptr);
|
||||
sigaction(SIGTERM, &old_sigterm, nullptr);
|
||||
g_foreground_child_pid = 0;
|
||||
|
||||
int exit_code = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
|
||||
if (exit_code != 0) {
|
||||
|
||||
Reference in New Issue
Block a user