From: Ian Kent <raven@themaw.net>
authorzoulasc <christos@zoulas.com>
Fri, 21 Mar 2014 00:52:54 +0000 (20:52 -0400)
committerzoulasc <christos@zoulas.com>
Fri, 21 Mar 2014 00:52:54 +0000 (20:52 -0400)
It's possible (and likely) a SIGCHLD signal can arrive while in syslog(2)
and also attempt log log a message leading to deadlock.

libamu/xutil.c

index 28286f6111fdf47bebb26f4ad0522f54a44968ca..1159fe5ec83ecf9ef5dfd0800e1ca50f7af83a7b 100644 (file)
@@ -422,14 +422,33 @@ debug_option(char *opt)
 void
 dplog(const char *fmt, ...)
 {
+#ifdef HAVE_SIGACTION
+  sigset_t old, chld;
+#else /* not HAVE_SIGACTION */
+  int mask;
+#endif /* not HAVE_SIGACTION */
   va_list ap;
 
+#ifdef HAVE_SIGACTION
+  sigemptyset(&chld);
+  sigaddset(&chld, SIGCHLD);
+#else /* not HAVE_SIGACTION */
+  mask = sigblock(sigmask(SIGCHLD));
+#endif /* not HAVE_SIGACTION */
+
+  sigprocmask(SIG_BLOCK, &chld, &old);
   if (!logfp)
     logfp = stderr;            /* initialize before possible first use */
 
   va_start(ap, fmt);
   real_plog(XLOG_DEBUG, fmt, ap);
   va_end(ap);
+
+#ifdef HAVE_SIGACTION
+  sigprocmask(SIG_SETMASK, &old, NULL);
+#else /* not HAVE_SIGACTION */
+  mask = sigblock(sigmask(SIGCHLD));
+#endif /* not HAVE_SIGACTION */
 }
 #endif /* DEBUG */
 
@@ -437,14 +456,33 @@ dplog(const char *fmt, ...)
 void
 plog(int lvl, const char *fmt, ...)
 {
+#ifdef HAVE_SIGACTION
+  sigset_t old, chld;
+#else /* not HAVE_SIGACTION */
+  int mask;
+#endif /* not HAVE_SIGACTION */
   va_list ap;
 
+#ifdef HAVE_SIGACTION
+  sigemptyset(&chld);
+  sigaddset(&chld, SIGCHLD);
+  sigprocmask(SIG_BLOCK, &chld, &old);
+#else /* not HAVE_SIGACTION */
+  mask = sigblock(sigmask(SIGCHLD));
+#endif /* not HAVE_SIGACTION */
+
   if (!logfp)
     logfp = stderr;            /* initialize before possible first use */
 
   va_start(ap, fmt);
   real_plog(lvl, fmt, ap);
   va_end(ap);
+
+#ifdef HAVE_SIGACTION
+  sigprocmask(SIG_SETMASK, &old, NULL);
+#else /* not HAVE_SIGACTION */
+  sigsetmask(mask);
+#endif /* not HAVE_SIGACTION */
 }