[libvirt] [PATCH] use sa_handler instead of sa_sigaction when SA_SIGINFO is not defined

Wen Congyang wency at cn.fujitsu.com
Fri Apr 20 03:10:08 UTC 2012


POSIX requires that we use sa_sigaction if sa_flags includes SA_SIGINFO,
and that we use sa_handler otherwise. But we still use sa_sigaction
when SA_SIGINFO is not defined. Practice says it will work, but theory
says we can't rely on it to work.

---
 src/rpc/virnetserver.c |   25 +++++++++++++++++++++++--
 tools/virsh.c          |   35 ++++++++++++++++++++++++++++-------
 2 files changed, 51 insertions(+), 9 deletions(-)

diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
index 3965fc2..131ecb4 100644
--- a/src/rpc/virnetserver.c
+++ b/src/rpc/virnetserver.c
@@ -270,8 +270,12 @@ error:
 }
 
 
+#ifdef SA_SIGINFO
 static void virNetServerFatalSignal(int sig, siginfo_t *siginfo ATTRIBUTE_UNUSED,
                                     void *context ATTRIBUTE_UNUSED)
+#else
+static void virNetServerFatalSignal(int sig)
+#endif
 {
     struct sigaction sig_action;
     int origerrno;
@@ -286,6 +290,7 @@ static void virNetServerFatalSignal(int sig, siginfo_t *siginfo ATTRIBUTE_UNUSED
 #ifdef SIGUSR2
     if (sig != SIGUSR2) {
 #endif
+        memset(&sig_action, 0, sizeof(sig_action));
         sig_action.sa_handler = SIG_DFL;
         sigaction(sig, &sig_action, NULL);
         raise(sig);
@@ -362,7 +367,12 @@ virNetServerPtr virNetServerNew(size_t min_workers,
      * catch fatal errors to dump a log, also hook to USR2 for dynamic
      * debugging purposes or testing
      */
+#ifdef SA_SIGINFO
     sig_action.sa_sigaction = virNetServerFatalSignal;
+    sig_action.sa_flags = SA_SIGINFO;
+#else
+    sig_action.sa_handler = virNetServerFatalSignal;
+#endif
     sigaction(SIGFPE, &sig_action, NULL);
     sigaction(SIGSEGV, &sig_action, NULL);
     sigaction(SIGILL, &sig_action, NULL);
@@ -420,17 +430,28 @@ static sig_atomic_t sigErrors = 0;
 static int sigLastErrno = 0;
 static int sigWrite = -1;
 
+#ifdef SA_SIGINFO
 static void virNetServerSignalHandler(int sig, siginfo_t * siginfo,
                                       void* context ATTRIBUTE_UNUSED)
+#else
+static void virNetServerSignalHandler(int sig)
+#endif
 {
     int origerrno;
     int r;
+    siginfo_t temp_siginfo;
+
+#ifdef SA_SIGINFO
+    memcpy(&temp_siginfo, siginfo, sizeof(temp_siginfo));
+#else
+    memset(&temp_siginfo, 0, sizeof(temp_siginfo));
+#endif
 
     /* set the sig num in the struct */
-    siginfo->si_signo = sig;
+    temp_siginfo.si_signo = sig;
 
     origerrno = errno;
-    r = safewrite(sigWrite, siginfo, sizeof(*siginfo));
+    r = safewrite(sigWrite, &temp_siginfo, sizeof(temp_siginfo));
     if (r == -1) {
         sigErrors++;
         sigLastErrno = errno;
diff --git a/tools/virsh.c b/tools/virsh.c
index 6168a13..cb64e81 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -579,9 +579,13 @@ out:
 
 static volatile sig_atomic_t intCaught = 0;
 
+#ifdef SA_SIGINFO
 static void vshCatchInt(int sig ATTRIBUTE_UNUSED,
                         siginfo_t *siginfo ATTRIBUTE_UNUSED,
                         void *context ATTRIBUTE_UNUSED)
+#else
+static void vshCatchInt(int sig ATTRIBUTE_UNUSED)
+#endif
 {
     intCaught = 1;
 }
@@ -591,23 +595,25 @@ static void vshCatchInt(int sig ATTRIBUTE_UNUSED,
  */
 static int disconnected = 0; /* we may have been disconnected */
 
-/* Gnulib doesn't guarantee SA_SIGINFO support.  */
-#ifndef SA_SIGINFO
-# define SA_SIGINFO 0
-#endif
-
 /*
  * vshCatchDisconnect:
  *
  * We get here when a SIGPIPE is being raised, we can't do much in the
  * handler, just save the fact it was raised
  */
+#ifdef SA_SIGINFO
 static void vshCatchDisconnect(int sig, siginfo_t *siginfo,
                                void *context ATTRIBUTE_UNUSED) {
-    if (sig == SIGPIPE ||
-        (SA_SIGINFO && siginfo->si_signo == SIGPIPE))
+    if (sig == SIGPIPE || siginfo->si_signo == SIGPIPE)
+        disconnected++;
+}
+#else
+static void vshCatchDisconnect(int sig)
+{
+    if (sig == SIGPIPE)
         disconnected++;
 }
+#endif
 
 /*
  * vshSetupSignals:
@@ -619,8 +625,13 @@ static void
 vshSetupSignals(void) {
     struct sigaction sig_action;
 
+#ifdef SA_SIGINFO
     sig_action.sa_sigaction = vshCatchDisconnect;
     sig_action.sa_flags = SA_SIGINFO;
+#else
+    sig_action.sa_handler = vshCatchDisconnect;
+    sig_action.sa_flags = 0;
+#endif
     sigemptyset(&sig_action.sa_mask);
 
     sigaction(SIGPIPE, &sig_action, NULL);
@@ -7254,8 +7265,13 @@ vshWatchJob(vshControl *ctl,
     sigaddset(&sigmask, SIGINT);
 
     intCaught = 0;
+#ifdef SA_SIGINFO
     sig_action.sa_sigaction = vshCatchInt;
     sig_action.sa_flags = SA_SIGINFO;
+#else
+    sig_action.sa_handler = vshCatchInt;
+    sig_action.sa_flags = 0;
+#endif
     sigemptyset(&sig_action.sa_mask);
     sigaction(SIGINT, &sig_action, &old_sig_action);
 
@@ -7631,8 +7647,13 @@ cmdBlockPull(vshControl *ctl, const vshCmd *cmd)
         sigaddset(&sigmask, SIGINT);
 
         intCaught = 0;
+#ifdef SA_SIGINFO
         sig_action.sa_sigaction = vshCatchInt;
         sig_action.sa_flags = SA_SIGINFO;
+#else
+        sig_action.sa_handler = vshCatchInt;
+        sig_action.sa_flags = 0;
+#endif
         sigemptyset(&sig_action.sa_mask);
         sigaction(SIGINT, &sig_action, &old_sig_action);
 
-- 
1.7.1




More information about the libvir-list mailing list