signals: Make signal_name() thread-safe.
authorBen Pfaff <blp@nicira.com>
Tue, 16 Apr 2013 22:25:10 +0000 (15:25 -0700)
committerBen Pfaff <blp@nicira.com>
Wed, 5 Jun 2013 19:46:59 +0000 (12:46 -0700)
Signed-off-by: Ben Pfaff <blp@nicira.com>
lib/fatal-signal.c
lib/process.c
lib/signals.c
lib/signals.h

index 66c0445..8c66ef5 100644 (file)
@@ -155,8 +155,10 @@ fatal_signal_run(void)
 
     sig_nr = stored_sig_nr;
     if (sig_nr != SIG_ATOMIC_MAX) {
+        char namebuf[SIGNAL_NAME_BUFSIZE];
+
         VLOG_WARN("terminating with signal %d (%s)",
-                  (int)sig_nr, signal_name(sig_nr));
+                  (int)sig_nr, signal_name(sig_nr, namebuf, sizeof namebuf));
         call_hooks(sig_nr);
 
         /* Re-raise the signal with the default handling so that the program
index 9fe742c..0aa1842 100644 (file)
@@ -348,9 +348,15 @@ process_status_msg(int status)
     if (WIFEXITED(status)) {
         ds_put_format(&ds, "exit status %d", WEXITSTATUS(status));
     } else if (WIFSIGNALED(status)) {
-        ds_put_format(&ds, "killed (%s)", signal_name(WTERMSIG(status)));
+        char namebuf[SIGNAL_NAME_BUFSIZE];
+
+        ds_put_format(&ds, "killed (%s)",
+                      signal_name(WTERMSIG(status), namebuf, sizeof namebuf));
     } else if (WIFSTOPPED(status)) {
-        ds_put_format(&ds, "stopped (%s)", signal_name(WSTOPSIG(status)));
+        char namebuf[SIGNAL_NAME_BUFSIZE];
+
+        ds_put_format(&ds, "stopped (%s)",
+                      signal_name(WSTOPSIG(status), namebuf, sizeof namebuf));
     } else {
         ds_put_format(&ds, "terminated abnormally (%x)", status);
     }
index c47fefa..99a36a4 100644 (file)
@@ -137,37 +137,38 @@ signal_handler(int signr)
     }
 }
 
-/* Returns the name of signal 'signum' as a string.  The string may be in a
- * static buffer that is reused from one call to the next.
+/* Returns the name of signal 'signum' as a string.  The return value is either
+ * a statically allocated constant string or the 'bufsize'-byte buffer
+ * 'namebuf'.  'bufsize' should be at least SIGNAL_NAME_BUFSIZE.
  *
  * The string is probably a (possibly multi-word) description of the signal
  * (e.g. "Hangup") instead of just the stringified version of the macro
  * (e.g. "SIGHUP"). */
 const char *
-signal_name(int signum)
+signal_name(int signum, char *namebuf, size_t bufsize)
 {
-    const char *name = NULL;
-
 #if HAVE_DECL_SYS_SIGLIST
     if (signum >= 0 && signum < ARRAY_SIZE(sys_siglist)) {
-        name = sys_siglist[signum];
+        const char *name = sys_siglist[signum];
+        if (name) {
+            return name;
+        }
     }
 #endif
 
-    if (!name) {
-        static char buffer[7 + INT_STRLEN(int) + 1];
-        sprintf(buffer, "signal %d", signum);
-        name = buffer;
-    }
-    return name;
+    snprintf(namebuf, bufsize, "signal %d", signum);
+    return namebuf;
 }
 
 void
 xsigaction(int signum, const struct sigaction *new, struct sigaction *old)
 {
     if (sigaction(signum, new, old)) {
+        char namebuf[SIGNAL_NAME_BUFSIZE];
+
         VLOG_FATAL("sigaction(%s) failed (%s)",
-                   signal_name(signum), strerror(errno));
+                   signal_name(signum, namebuf, sizeof namebuf),
+                   strerror(errno));
     }
 }
 
index 641bcbb..015d329 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <signal.h>
 #include <stdbool.h>
+#include "type-props.h"
 
 void signal_init(void);
 
@@ -28,7 +29,8 @@ void signal_unregister(struct signal *);
 bool signal_poll(struct signal *);
 void signal_wait(struct signal *);
 
-const char *signal_name(int signum);
+enum { SIGNAL_NAME_BUFSIZE = 7 + INT_STRLEN(int) + 1 };
+const char *signal_name(int signum, char *namebuf, size_t bufsize);
 
 void xsigaction(int signum, const struct sigaction *, struct sigaction *old);
 void xpthread_sigmask(int how, const sigset_t *, sigset_t *old);