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;

Reply via email to