commit: 252b332a0430d76e3f530b118d613f8c4aad414c
Author: Michał Górny <mgorny <AT> gentoo <DOT> org>
AuthorDate: Sat Nov 29 13:50:17 2025 +0000
Commit: Michał Górny <mgorny <AT> gentoo <DOT> org>
CommitDate: Sat Nov 29 13:50:17 2025 +0000
URL: https://gitweb.gentoo.org/proj/steve.git/commit/?id=252b332a
Handle signals gracefully in stevie
Signed-off-by: Michał Górny <mgorny <AT> gentoo.org>
stevie.cxx | 40 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/stevie.cxx b/stevie.cxx
index 28a0d88..59ccd41 100644
--- a/stevie.cxx
+++ b/stevie.cxx
@@ -28,10 +28,48 @@ struct token_guard {
}
};
+pid_t pid = -1;
+
+void signal_handler(int signum, siginfo_t *, void *)
+{
+ if (pid != -1) {
+ std::print("stevie: passing signal SIG{} to child {}, repeat to
force termination\n",
+ sigabbrev_np(signum), pid);
+ if (kill(pid, signum) == -1 && errno != ESRCH) {
+ perror("Unable to pass signal to child process");
+ exit(1);
+ }
+ }
+
+ struct sigaction sigact{};
+ sigact.sa_handler = SIG_DFL;
+ if (sigaction(signum, &sigact, NULL) == -1) {
+ perror("Unable to restore default signal handler");
+ exit(1);
+ }
+ /* if we didn't fork yet, just reraise */
+ if (pid == -1) {
+ if (raise(signum) == -1) {
+ perror("Unable to reraise signal");
+ exit(1);
+ }
+ }
+}
+
static int run_command(int jobserver_fd, char **argv, const char
*jobserver_path)
{
char job_token;
+ struct sigaction sigact{};
+ sigact.sa_sigaction = signal_handler;
+ sigact.sa_flags = SA_SIGINFO;
+ for (int signum : {SIGHUP, SIGINT, SIGTERM, SIGUSR1, SIGUSR2}) {
+ if (sigaction(signum, &sigact, NULL) == -1) {
+ perror("Setting signal handler failed");
+ return 1;
+ }
+ }
+
ssize_t res;
while ((res = read(jobserver_fd, &job_token, 1)) == -1 && errno ==
EINTR);
if (res == 0) {
@@ -43,7 +81,7 @@ static int run_command(int jobserver_fd, char **argv, const
char *jobserver_path
return 1;
}
- pid_t pid = fork();
+ pid = fork();
if (pid == 0) {
const char *old_makeflags = getenv("MAKEFLAGS");
std::string new_makeflags;