Andrew Black wrote:
Greetings all.

Attached is a patch that aims to resolve an old issue with the exec utility on UNIX. The problem observed is that when a kill signal is sent to the exec utility, the child processes aren't killed. This patch has been tested on Linux IA-32 and HPUX-11.23 on IA-64 (chosen due to previous issues with signals).

Looks good to me. Unless Farid objects go ahead and commit it.

Thanks
Martin


--Andrew Black

Changelog:
    * exec.cpp (alarm_timeout) [!_WIN32]: Update documentation.
    (kill_signal) [!WIN32]: Add file local variable to track signal used to
    kill process.
    (handle_term_signal) [!_WIN32]: Add new callback function...
    (wait_for_child) [!_WIN32]: ... Used here for SIGHUP, SIGINT, SIGQUIT,
    and SIGTERM signals (via sigaction).  Handlers are cleared if
    kill_signal is set and the signal contained within is raise()ed.


------------------------------------------------------------------------

Index: util/exec.cpp
===================================================================
--- util/exec.cpp       (revision 483585)
+++ util/exec.cpp       (working copy)
@@ -64,10 +64,19 @@
    Value is 1 when alarm has been triggered and hasn't been handled
@see handle_alrm
+   @see handle_term_signal
 */
 static int alarm_timeout;
/**
+   Record of fatal signal recieved.  Used to raise() the signal again after
+   child process has been killed.
+
+   @see handle_term_signal
+*/
+static int kill_signal;
+
+/**
     Utility macro to generate a signal number/name pair.
@parm val 'short' signal name (no leading SIG) to generate pair for.
@@ -360,6 +369,22 @@
         alarm_timeout = 1;
 }
+/**
+   Callback used to gracefully terminate the utility if signaled to do so
+   while running a target
+
+ @param signo the signal recieved (should be in {SIGHUP, SIGINT, SIGQUIT, + SIGTERM})
+   @see alarm_timeout
+
+*/
+static void
+handle_term_signal (int signo)
+{
+    kill_signal = signo;
+    alarm_timeout = 1;
+}
+
 typedef void (*alarm_handler)(int);
#ifdef __cplusplus
@@ -428,6 +453,19 @@
sigaction (SIGALRM, &act, 0); + /* Set handlers for SIGHUP, SIGINT, SIGQUIT, SIGTERM so we can kill the
+       child process prior to dieing.
+    */
+    kill_signal = 0;
+
+    phandler = handle_term_signal;
+    memcpy (&act.sa_handler, &phandler, sizeof act.sa_handler);
+
+    sigaction (SIGHUP, &act, 0);
+    sigaction (SIGINT, &act, 0);
+    sigaction (SIGQUIT, &act, 0);
+    sigaction (SIGTERM, &act, 0);
+
     if (timeout > 0)
         alarm (timeout);
@@ -558,6 +596,20 @@
         ++siginx;
         sleep (1);
     }
+
+    /* Check if we were signaled to quit. */
+    if (kill_signal) {
+        /* Reset the handlers to normal */
+        act.sa_handler = SIG_DFL;
+        sigaction (SIGHUP, &act, 0);
+        sigaction (SIGINT, &act, 0);
+        sigaction (SIGQUIT, &act, 0);
+        sigaction (SIGTERM, &act, 0);
+
+        if (0 > raise (kill_signal))
+            terminate (1, "raise(%s) failed: %s\n",
+                       get_signame (kill_signal), strerror (errno));
+    }
 }
/**

Reply via email to