[exim-dev] [PATCH 1/2] exiwhat: Minimal fix for signal safet…

Top Page
Delete this message
Reply to this message
Author: Tony Finch
Date:  
To: exim-dev
Subject: [exim-dev] [PATCH 1/2] exiwhat: Minimal fix for signal safety bugs.
exiwhat sends a SIGUSR1 to all exim processes to make them write
their status to the process log. This is all done in the signal
handler, but the logging code makes a number of calls that are
not signal safe.

Firstly, obtaining and formatting the timestamp is not safe.
Doing so is unnecessary since exiwhat strips off the timestamp.
This patch skips the timestamp code.

Secondly, exim closes all the logs after writing the process
log. Closing syslog is not signal safe, and isn't necessary.
The logging code already closes the process log immediately
after writing to it, so just remove the log_close_all() call.

Both of these can make libc attempt to acquire a lock recursively,
thereby making exim hang.
---
 src/src/exim.c      |    1 -
 src/src/exiwhat.src |    2 +-
 src/src/log.c       |   25 +++++++++++++++----------
 3 files changed, 16 insertions(+), 12 deletions(-)


diff --git a/src/src/exim.c b/src/src/exim.c
index bda6190..4c9867f 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -156,7 +156,6 @@ usr1_handler(int sig)
 {
 sig = sig;      /* Keep picky compilers happy */
 log_write(0, LOG_PROCESS, "%s", process_info);
-log_close_all();
 os_restarting_signal(SIGUSR1, usr1_handler);
 }


diff --git a/src/src/exiwhat.src b/src/src/exiwhat.src
index 5f81507..3fd70f5 100644
--- a/src/src/exiwhat.src
+++ b/src/src/exiwhat.src
@@ -130,7 +130,7 @@ fi
sleep 1

if [ ! -s ${log} ] ; then echo "No exim process data" ;
- else sed 's/^[0-9-]* [0-9:]* \([+-][0-9]* \)*\(\[[0-9]\+\] \)\?//' ${log} | sort -n | uniq ; fi
+ else sort -n ${log} | uniq ; fi


# End of exiwhat
diff --git a/src/src/log.c b/src/src/log.c
index 1d2c8f5..79ea4cc 100644
--- a/src/src/log.c
+++ b/src/src/log.c
@@ -752,19 +752,24 @@ if (!write_rejectlog) flags &= ~LOG_REJECT;
id except for the process log and when called by a utility. */

ptr = log_buffer;
-sprintf(CS ptr, "%s ", tod_stamp(tod_log));
-while(*ptr) ptr++;
-
-if ((log_extra_selector & LX_pid) != 0)
- {
- sprintf(CS ptr, "[%d] ", (int)getpid());
- while (*ptr) ptr++;
- }

-if (really_exim && (flags & LOG_PROCESS) == 0 && message_id[0] != 0)
+/* Omit the timestamp in the process log because it is not signal-safe.*/
+if ((flags & LOG_PROCESS) == 0)
   {
-  sprintf(CS ptr, "%s ", message_id);
+  sprintf(CS ptr, "%s ", tod_stamp(tod_log));
   while(*ptr) ptr++;
+
+  if ((log_extra_selector & LX_pid) != 0)
+    {
+    sprintf(CS ptr, "[%d] ", (int)getpid());
+    while (*ptr) ptr++;
+    }
+
+  if (really_exim && message_id[0] != 0)
+    {
+    sprintf(CS ptr, "%s ", message_id);
+    while(*ptr) ptr++;
+    }
   }


if ((flags & LOG_CONFIG) != 0) ptr = log_config_info(ptr, flags);
--
1.7.3.GIT