[exim-cvs] Handle short writes on logfiles.

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] Handle short writes on logfiles.
Gitweb: http://git.exim.org/exim.git/commitdiff/0599f9cfa6febfb0aa5c106510d72e49e72a65c4
Commit:     0599f9cfa6febfb0aa5c106510d72e49e72a65c4
Parent:     6253ef3b6d4f0cf70fdc1418827b84d2cc2897bf
Author:     Phil Pennock <pdp@???>
AuthorDate: Tue Nov 22 14:14:57 2011 -0500
Committer:  Phil Pennock <pdp@???>
CommitDate: Tue Nov 22 14:14:57 2011 -0500


    Handle short writes on logfiles.


    fixes bug 1053
---
 doc/doc-txt/ChangeLog |    8 ++++++
 src/src/log.c         |   61 +++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 59 insertions(+), 10 deletions(-)


diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 1d95772..ec6dfcb 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -1,6 +1,14 @@
Change log file for Exim from version 4.21
-------------------------------------------

+Exim version 4.78
+-----------------
+
+PP/01 Handle short writes when writing local log-files.
+      In practice, only affects FreeBSD (8 onwards).
+      Bugzilla 1053, with thanks to Dmitry Isaikin.
+
+
 Exim version 4.77
 -----------------


diff --git a/src/src/log.c b/src/src/log.c
index 2be1ff2..bfd1fef 100644
--- a/src/src/log.c
+++ b/src/src/log.c
@@ -514,6 +514,49 @@ log_write(0, LOG_PANIC_DIE, "failed to write to %s: length=%d result=%d "


 /*************************************************
+*     Write to an fd, retrying after signals     *
+*************************************************/
+
+/* Basic write to fd for logs, handling EINTR.
+
+Arguments:
+  fd        the fd to write to
+  buf       the string to write
+  length    the string length being written
+
+Returns:
+  length actually written, persisting an errno from write()
+*/
+ssize_t
+write_to_fd_buf(int fd, uschar *buf, size_t length)
+{
+ssize_t wrote;
+size_t total_written = 0;
+uschar *p = buf;
+size_t left = length;
+
+while (1)
+  {
+  wrote = write(fd, p, left);
+  if (wrote == (ssize_t)-1)
+    {
+    if (errno == EINTR) continue;
+    return wrote;
+    }
+  total_written += wrote;
+  if (wrote == left)
+    break;
+  else
+    {
+    p += wrote;
+    left -= wrote;
+    }
+  }
+return total_written;
+}
+
+
+/*************************************************
 *            Write message to log file           *
 *************************************************/


@@ -574,7 +617,7 @@ void
log_write(unsigned int selector, int flags, const char *format, ...)
{
uschar *ptr;
-int length, rc;
+int length;
int paniclogfd;
ssize_t written_len;
va_list ap;
@@ -892,11 +935,7 @@ if ((flags & LOG_MAIN) != 0 &&

     /* Failing to write to the log is disastrous */


-    while (
-        ((written_len = write(mainlogfd, log_buffer, length)) == (ssize_t)-1)
-        &&
-        (errno == EINTR)
-        ) /**/;
+    written_len = write_to_fd_buf(mainlogfd, log_buffer, length);
     if (written_len != length)
       {
       log_write_failed(US"main log", length, written_len);
@@ -1019,9 +1058,10 @@ if ((flags & LOG_REJECT) != 0)
       if (fstat(rejectlogfd, &statbuf) >= 0) rejectlog_inode = statbuf.st_ino;
       }


-    if ((rc = write(rejectlogfd, log_buffer, length)) != length)
+    written_len = write_to_fd_buf(rejectlogfd, log_buffer, length);
+    if (written_len != length)
       {
-      log_write_failed(US"reject log", length, rc);
+      log_write_failed(US"reject log", length, written_len);
       /* That function does not return */
       }
     }
@@ -1055,12 +1095,13 @@ if ((flags & LOG_PANIC) != 0)
     if (panic_save_buffer != NULL)
       (void) write(paniclogfd, panic_save_buffer, Ustrlen(panic_save_buffer));


-    if ((rc = write(paniclogfd, log_buffer, length)) != length)
+    written_len = write_to_fd_buf(paniclogfd, log_buffer, length);
+    if (written_len != length)
       {
       int save_errno = errno;
       write_syslog(LOG_CRIT, log_buffer);
       sprintf(CS log_buffer, "write failed on panic log: length=%d result=%d "
-        "errno=%d (%s)", length, rc, save_errno, strerror(save_errno));
+        "errno=%d (%s)", length, (int)written_len, save_errno, strerror(save_errno));
       write_syslog(LOG_CRIT, log_buffer);
       flags |= LOG_PANIC_DIE;
       }