GNU/Hurd: retry EINTR returns from pipe I/O
authorJeremy Harris <jgh146exb@wizmail.org>
Tue, 17 Dec 2019 20:35:28 +0000 (20:35 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Wed, 18 Dec 2019 00:07:22 +0000 (00:07 +0000)
Replaces: a76f64c3d4

doc/doc-txt/ChangeLog
src/OS/Makefile-Base
src/OS/os.c-GNU
src/OS/os.h-GNU
src/src/deliver.c
src/src/osfunctions.h
src/src/queue.c
src/src/rda.c
src/src/transport.c

index f4963389ee85f308496a0d30f1bf5ac7d9d5416f..13468ae46692e4ccfe9c2a448a18ecc7576fcac9 100644 (file)
@@ -53,6 +53,9 @@ JH/13 Bug 2498: Reset a counter used for ARC verify before handling another
       the following one did not, a crash could result when adding an
       Authentication-Results: header.
 
+JH/14 On GNU/Hurd, retry EINTR returns from I/O on pipes, which seem to occur
+      frequently.
+
 
 Exim version 4.93
 -----------------
index 36af8308d05333cb6a43623c7a4bbb2a4373c130..1ab3ac35f36388a339ded06b53b2053612c4d950 100644 (file)
@@ -644,7 +644,8 @@ HDRS  =     blob.h \
        mytypes.h \
        sha_ver.h \
        structs.h \
-       os.h
+       os.h \
+       osfunctions.h
 PHDRS = ../config.h \
        ../dbfunctions.h \
        ../dbstuff.h \
@@ -655,7 +656,8 @@ PHDRS = ../config.h \
        ../macros.h \
        ../mytypes.h \
        ../structs.h \
-       ../os.h
+       ../os.h \
+       ../osfunctions.h
 
 .SUFFIXES: .o .c
 .c.o:;  @echo "$(CC) $*.c"
index e5d6ff66cd7b6f31a1338187eaec4f666e67b09f..06226839b68b051b6e20d432a6a92b0428ceec92 100644 (file)
@@ -52,4 +52,39 @@ return -1;
 }
 #endif  /* OS_LOAD_AVERAGE */
 
+
+ssize_t
+os_pipe_read(int fd, void * buf, size_t count)
+{
+for (int rc, retries = 10; retries > 0; retries--)
+  {
+  if ((rc = read(fd, buf, count) >= 0) break;
+  if (rc != -1 || errno != EINTR) break;
+  }
+return rc;
+}
+
+
+ssize_t
+os_pipe_write(int fd, void * buf, size_t count)
+{
+for (int rc, retries = 10; retries > 0; retries--)
+  {
+  if ((rc = write(fd, buf, count) >= 0) break;
+  if (rc != -1 || errno != EINTR) break;
+  }
+return rc;
+}
+
+ssize_t
+os_pipe_writev(int fd, const struct iovec * iov, int iovcnt
+{
+for (int rc, retries = 10; retries > 0; retries--)
+  {
+  if ((rc = writev(fd, iov, iovcnt) >= 0) break;
+  if (rc != -1 || errno != EINTR) break;
+  }
+return rc;
+}
+
 /* End of os.c-GNU */
index 1de2e3e849dbba3b457145d301351b0db40274d7..772d278addf5315ac5341103952a361f0c01b0f9 100644 (file)
@@ -21,7 +21,11 @@ typedef struct flock flock_t;
 #define ICONV_ARG2_TYPE const char **
 
 /* setgroups(0, NULL) succeeds, and drops the gid group
-as well as any supplementary groups*/
+as well as any supplementary groups */
 #define OS_SETGROUPS_ZERO_DROPS_ALL
 
+/* reads and writes on pipes frequently return EINTR.  We provide
+a routine to retry that */
+#define OS_PIPE_RW_EINTR
+
 /* End */
index 733fe6ff5946cc0ebe616fafce20f0a74fca55d9..8c05934483a10d183cae2aedfc12bf7bded28e9a 100644 (file)
@@ -2402,14 +2402,14 @@ if ((pid = fork()) == 0)
     uschar *s;
     int ret;
 
-    if(  (ret = write(pfd[pipe_write], &addr2->transport_return, sizeof(int))) != sizeof(int)
-      || (ret = write(pfd[pipe_write], &transport_count, sizeof(transport_count))) != sizeof(transport_count)
-      || (ret = write(pfd[pipe_write], &addr2->flags, sizeof(addr2->flags))) != sizeof(addr2->flags)
-      || (ret = write(pfd[pipe_write], &addr2->basic_errno,    sizeof(int))) != sizeof(int)
-      || (ret = write(pfd[pipe_write], &addr2->more_errno,     sizeof(int))) != sizeof(int)
-      || (ret = write(pfd[pipe_write], &addr2->delivery_usec,  sizeof(int))) != sizeof(int)
-      || (ret = write(pfd[pipe_write], &addr2->special_action, sizeof(int))) != sizeof(int)
-      || (ret = write(pfd[pipe_write], &addr2->transport,
+    if(  (ret = os_pipe_write(pfd[pipe_write], &addr2->transport_return, sizeof(int))) != sizeof(int)
+      || (ret = os_pipe_write(pfd[pipe_write], &transport_count, sizeof(transport_count))) != sizeof(transport_count)
+      || (ret = os_pipe_write(pfd[pipe_write], &addr2->flags, sizeof(addr2->flags))) != sizeof(addr2->flags)
+      || (ret = os_pipe_write(pfd[pipe_write], &addr2->basic_errno,    sizeof(int))) != sizeof(int)
+      || (ret = os_pipe_write(pfd[pipe_write], &addr2->more_errno,     sizeof(int))) != sizeof(int)
+      || (ret = os_pipe_write(pfd[pipe_write], &addr2->delivery_usec,  sizeof(int))) != sizeof(int)
+      || (ret = os_pipe_write(pfd[pipe_write], &addr2->special_action, sizeof(int))) != sizeof(int)
+      || (ret = os_pipe_write(pfd[pipe_write], &addr2->transport,
         sizeof(transport_instance *))) != sizeof(transport_instance *)
 
     /* For a file delivery, pass back the local part, in case the original
@@ -2417,8 +2417,8 @@ if ((pid = fork()) == 0)
     logging. */
 
       || (testflag(addr2, af_file)
-          && (  (ret = write(pfd[pipe_write], &local_part_length, sizeof(int))) != sizeof(int)
-             || (ret = write(pfd[pipe_write], addr2->local_part, local_part_length)) != local_part_length
+          && (  (ret = os_pipe_write(pfd[pipe_write], &local_part_length, sizeof(int))) != sizeof(int)
+             || (ret = os_pipe_write(pfd[pipe_write], addr2->local_part, local_part_length)) != local_part_length
             )
         )
       )
@@ -2430,8 +2430,8 @@ if ((pid = fork()) == 0)
     for (i = 0, s = addr2->message; i < 2; i++, s = addr2->user_message)
       {
       int message_length = s ? Ustrlen(s) + 1 : 0;
-      if(  (ret = write(pfd[pipe_write], &message_length, sizeof(int))) != sizeof(int)
-        || message_length > 0  && (ret = write(pfd[pipe_write], s, message_length)) != message_length
+      if(  (ret = os_pipe_write(pfd[pipe_write], &message_length, sizeof(int))) != sizeof(int)
+        || message_length > 0  && (ret = os_pipe_write(pfd[pipe_write], s, message_length)) != message_length
        )
         log_write(0, LOG_MAIN|LOG_PANIC, "Failed writing transport results to pipe: %s",
          ret == -1 ? strerror(errno) : "short write");
@@ -2464,26 +2464,26 @@ will remain. Afterwards, close the reading end. */
 
 for (addr2 = addr; addr2; addr2 = addr2->next)
   {
-  if ((len = read(pfd[pipe_read], &status, sizeof(int))) > 0)
+  if ((len = os_pipe_read(pfd[pipe_read], &status, sizeof(int))) > 0)
     {
     int i;
     uschar **sptr;
 
     addr2->transport_return = status;
-    len = read(pfd[pipe_read], &transport_count,
+    len = os_pipe_read(pfd[pipe_read], &transport_count,
       sizeof(transport_count));
-    len = read(pfd[pipe_read], &addr2->flags, sizeof(addr2->flags));
-    len = read(pfd[pipe_read], &addr2->basic_errno,    sizeof(int));
-    len = read(pfd[pipe_read], &addr2->more_errno,     sizeof(int));
-    len = read(pfd[pipe_read], &addr2->delivery_usec,  sizeof(int));
-    len = read(pfd[pipe_read], &addr2->special_action, sizeof(int));
-    len = read(pfd[pipe_read], &addr2->transport,
+    len = os_pipe_read(pfd[pipe_read], &addr2->flags, sizeof(addr2->flags));
+    len = os_pipe_read(pfd[pipe_read], &addr2->basic_errno,    sizeof(int));
+    len = os_pipe_read(pfd[pipe_read], &addr2->more_errno,     sizeof(int));
+    len = os_pipe_read(pfd[pipe_read], &addr2->delivery_usec,  sizeof(int));
+    len = os_pipe_read(pfd[pipe_read], &addr2->special_action, sizeof(int));
+    len = os_pipe_read(pfd[pipe_read], &addr2->transport,
       sizeof(transport_instance *));
 
     if (testflag(addr2, af_file))
       {
       int llen;
-      if (  read(pfd[pipe_read], &llen, sizeof(int)) != sizeof(int)
+      if (  os_pipe_read(pfd[pipe_read], &llen, sizeof(int)) != sizeof(int)
         || llen > 64*4 /* limit from rfc 5821, times I18N factor */
          )
        {
@@ -2493,7 +2493,7 @@ for (addr2 = addr; addr2; addr2 = addr2->next)
        }
       /* sanity-checked llen so disable the Coverity error */
       /* coverity[tainted_data] */
-      if (read(pfd[pipe_read], big_buffer, llen) != llen)
+      if (os_pipe_read(pfd[pipe_read], big_buffer, llen) != llen)
        {
        log_write(0, LOG_MAIN|LOG_PANIC, "bad local_part read"
          " from delivery subprocess");
@@ -2506,10 +2506,10 @@ for (addr2 = addr; addr2; addr2 = addr2->next)
     for (i = 0, sptr = &addr2->message; i < 2; i++, sptr = &addr2->user_message)
       {
       int message_length;
-      len = read(pfd[pipe_read], &message_length, sizeof(int));
+      len = os_pipe_read(pfd[pipe_read], &message_length, sizeof(int));
       if (message_length > 0)
         {
-        len = read(pfd[pipe_read], big_buffer, message_length);
+        len = os_pipe_read(pfd[pipe_read], big_buffer, message_length);
        big_buffer[big_buffer_size-1] = '\0';           /* guard byte */
         if (len > 0) *sptr = string_copy(big_buffer);
         }
@@ -4147,14 +4147,10 @@ if (PIPE_HEADER_SIZE != snprintf(CS pipe_header, PIPE_HEADER_SIZE+1, "%c%c%05ld"
 DEBUG(D_deliver) debug_printf("header write id:%c,subid:%c,size:%ld,final:%s\n",
                                  id, subid, (long)size, pipe_header);
 
-for (int retries = 10; retries > 0; retries--)
-  {
-  if ((ret = writev(fd, iov, 2)) == total_len) return;
-  if (ret != -1 || errno != EINTR) break;
-  }
-log_write(0, LOG_MAIN|LOG_PANIC_DIE,
-  "Failed writing transport result to pipe (%ld of %ld bytes): %s",
-  (long)ret, (long)total_len, ret == -1 ? strerror(errno) : "short write");
+if ((ret = os_pipe_writev(fd, iov, 2)) != total_len)
+  log_write(0, LOG_MAIN|LOG_PANIC_DIE,
+    "Failed writing transport result to pipe (%ld of %ld bytes): %s",
+    (long)ret, (long)total_len, ret == -1 ? strerror(errno) : "short write");
 }
 
 /*************************************************
index 4e6e9a91c9e86db3ece888d0ca13b897ffc91de3..8b3e14312b2e6c42f70ce7f5d73a5121c97d6b53 100644 (file)
@@ -3,6 +3,7 @@
 *************************************************/
 
 /* Copyright (c) University of Cambridge 1995 - 2016 */
+/* Copyright (c) The Exim Maintainers 2019 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Prototypes for os-specific functions. For utilities, we don't need the one
@@ -18,25 +19,35 @@ Notably, strsignal() is not in the Single Unix Specification (v3) and
 predicting constness is awkward. */
 
 #ifndef os_getloadavg
-extern int           os_getloadavg(void);
+ extern int           os_getloadavg(void);
 #endif
 #ifndef os_restarting_signal
-extern void          os_restarting_signal(int, void (*)(int));
+ extern void          os_restarting_signal(int, void (*)(int));
 #endif
 #ifndef os_non_restarting_signal
-extern void          os_non_restarting_signal(int, void (*)(int));
+ extern void          os_non_restarting_signal(int, void (*)(int));
 #endif
 #ifndef os_strexit
-extern const char   *os_strexit(int);     /* char to match os_strsignal */
+ extern const char   *os_strexit(int);     /* char to match os_strsignal */
 #endif
 #ifndef os_strsignal
-extern const char   *os_strsignal(int);   /* char to match strsignal in some OS */
+ extern const char   *os_strsignal(int);   /* char to match strsignal in some OS */
 #endif
 #ifndef os_unsetenv
-extern int           os_unsetenv(const uschar *);
+ extern int           os_unsetenv(const uschar *);
 #endif
 #ifndef os_getcwd
-extern uschar       *os_getcwd(uschar *, size_t);
+ extern uschar       *os_getcwd(uschar *, size_t);
+#endif
+
+#ifdef OS_PIPE_RW_EINTR
+ extern ssize_t os_pipe_read(int fd, void * buf, size_t count);
+ extern ssize_t os_pipe_write(int fd, void * buf, size_t count);
+ extern ssize_t os_pipe_writev(int fd, const struct iovec * iov, int iovcnt);
+#else
+# define os_pipe_read(fd, buf, count) read(fd, buf, count)
+# define os_pipe_write(fd, buf, count) write(fd, buf, count)
+# define os_pipe_writev(fd, buf, count) writev(fd, buf, count)
 #endif
 
 /* End of osfunctions.h */
index a578014262863091eb123a08bdaab249e2b6c567..06174332304ec340f974b0e1143e81d545f91713 100644 (file)
@@ -653,9 +653,10 @@ for (int i = queue_run_in_order ? -1 : 0;
     the mere fact that read() unblocks is enough. */
 
     set_process_info("running queue: waiting for children of %d", pid);
-    if ((status = read(pfd[pipe_read], buffer, sizeof(buffer))) != 0)
-      log_write(0, LOG_MAIN|LOG_PANIC, status > 0 ?
-       "queue run: unexpected data on pipe" : "queue run: error on pipe: %s",
+    if ((status = os_pipe_read(pfd[pipe_read], buffer, sizeof(buffer))) != 0)
+      log_write(0, LOG_MAIN|LOG_PANIC, status > 0
+       ? "queue run: unexpected data on pipe"
+       : "queue run: error on pipe read: %s",
        strerror(errno));
     (void)close(pfd[pipe_read]);
     set_process_info("running queue");
index 42b7b14a5557ee972fa6b20dece577c05583f6dc..341979df5603820ff2eb4014298835af4968cce6 100644 (file)
@@ -439,9 +439,9 @@ Returns:     -1 on error, else 0
 static int
 rda_write_string(int fd, const uschar *s)
 {
-int len = (s == NULL)? 0 : Ustrlen(s) + 1;
-return (  write(fd, &len, sizeof(int)) != sizeof(int)
-       || (s != NULL  &&  write(fd, s, len) != len)
+int len = s ? Ustrlen(s) + 1 : 0;
+return (  os_pipe_write(fd, &len, sizeof(int)) != sizeof(int)
+       || s  &&  write(fd, s, len) != len
        )
        ? -1 : 0;
 }
@@ -466,14 +466,14 @@ rda_read_string(int fd, uschar **sp)
 {
 int len;
 
-if (read(fd, &len, sizeof(int)) != sizeof(int)) return FALSE;
+if (os_pipe_read(fd, &len, sizeof(int)) != sizeof(int)) return FALSE;
 if (len == 0)
   *sp = NULL;
 else
   /* We know we have enough memory so disable the error on "len" */
   /* coverity[tainted_data] */
   /* We trust the data source, so untainted */
-  if (read(fd, *sp = store_get(len, FALSE), len) != len) return FALSE;
+  if (os_pipe_read(fd, *sp = store_get(len, FALSE), len) != len) return FALSE;
 return TRUE;
 }
 
@@ -641,8 +641,8 @@ if ((pid = fork()) == 0)
   /* Pass back whether it was a filter, and the return code and any overall
   error text via the pipe. */
 
-  if (  write(fd, filtertype, sizeof(int)) != sizeof(int)
-     || write(fd, &yield, sizeof(int)) != sizeof(int)
+  if (  os_pipe_write(fd, filtertype, sizeof(int)) != sizeof(int)
+     || os_pipe_write(fd, &yield, sizeof(int)) != sizeof(int)
      || rda_write_string(fd, *error) != 0
      )
     goto bad;
@@ -669,12 +669,12 @@ if ((pid = fork()) == 0)
     int i = 0;
     for (header_line * h = header_list; h != waslast->next; i++, h = h->next)
       if (  h->type == htype_old
-         && write(fd, &i, sizeof(i)) != sizeof(i)
+         && os_pipe_write(fd, &i, sizeof(i)) != sizeof(i)
         )
        goto bad;
 
     i = -1;
-    if (write(fd, &i, sizeof(i)) != sizeof(i))
+    if (os_pipe_write(fd, &i, sizeof(i)) != sizeof(i))
        goto bad;
 
     while (waslast != header_last)
@@ -682,7 +682,7 @@ if ((pid = fork()) == 0)
       waslast = waslast->next;
       if (waslast->type != htype_old)
        if (  rda_write_string(fd, waslast->text) != 0
-           || write(fd, &(waslast->type), sizeof(waslast->type))
+           || os_pipe_write(fd, &(waslast->type), sizeof(waslast->type))
              != sizeof(waslast->type)
           )
          goto bad;
@@ -693,7 +693,7 @@ if ((pid = fork()) == 0)
 
   /* Write the contents of the $n variables */
 
-  if (write(fd, filter_n, sizeof(filter_n)) != sizeof(filter_n))
+  if (os_pipe_write(fd, filter_n, sizeof(filter_n)) != sizeof(filter_n))
     goto bad;
 
   /* If the result was DELIVERED or NOTDELIVERED, we pass back the generated
@@ -711,10 +711,10 @@ if ((pid = fork()) == 0)
       int ig_err = addr->prop.ignore_error ? 1 : 0;
 
       if (  rda_write_string(fd, addr->address) != 0
-         || write(fd, &addr->mode, sizeof(addr->mode)) != sizeof(addr->mode)
-         || write(fd, &addr->flags, sizeof(addr->flags)) != sizeof(addr->flags)
+         || os_pipe_write(fd, &addr->mode, sizeof(addr->mode)) != sizeof(addr->mode)
+         || os_pipe_write(fd, &addr->flags, sizeof(addr->flags)) != sizeof(addr->flags)
          || rda_write_string(fd, addr->prop.errors_address) != 0
-         || write(fd, &ig_err, sizeof(ig_err)) != sizeof(ig_err)
+         || os_pipe_write(fd, &ig_err, sizeof(ig_err)) != sizeof(ig_err)
         )
        goto bad;
 
@@ -727,7 +727,7 @@ if ((pid = fork()) == 0)
 
       if (!addr->reply)
        {
-        if (write(fd, &reply_options, sizeof(int)) != sizeof(int))    /* 0 means no reply */
+        if (os_pipe_write(fd, &reply_options, sizeof(int)) != sizeof(int))    /* 0 means no reply */
          goto bad;
        }
       else
@@ -735,10 +735,10 @@ if ((pid = fork()) == 0)
         reply_options |= REPLY_EXISTS;
         if (addr->reply->file_expand) reply_options |= REPLY_EXPAND;
         if (addr->reply->return_message) reply_options |= REPLY_RETURN;
-        if (  write(fd, &reply_options, sizeof(int)) != sizeof(int)
-           || write(fd, &(addr->reply->expand_forbid), sizeof(int))
+        if (  os_pipe_write(fd, &reply_options, sizeof(int)) != sizeof(int)
+           || os_pipe_write(fd, &(addr->reply->expand_forbid), sizeof(int))
              != sizeof(int)
-           || write(fd, &(addr->reply->once_repeat), sizeof(time_t))
+           || os_pipe_write(fd, &(addr->reply->once_repeat), sizeof(time_t))
              != sizeof(time_t)
            || rda_write_string(fd, addr->reply->to) != 0
            || rda_write_string(fd, addr->reply->cc) != 0
@@ -787,8 +787,8 @@ empty pipe. Afterwards, close the reading end. */
 /* Read initial data, including yield and contents of *error */
 
 fd = pfd[pipe_read];
-if (read(fd, filtertype, sizeof(int)) != sizeof(int) ||
-    read(fd, &yield, sizeof(int)) != sizeof(int) ||
+if (os_pipe_read(fd, filtertype, sizeof(int)) != sizeof(int) ||
+    os_pipe_read(fd, &yield, sizeof(int)) != sizeof(int) ||
     !rda_read_string(fd, error)) goto DISASTER;
 
 /* Read the contents of any syntax error blocks if we have a pointer */
@@ -821,7 +821,7 @@ if (f.system_filtering)
   for (;;)
     {
     int n;
-    if (read(fd, &n, sizeof(int)) != sizeof(int)) goto DISASTER;
+    if (os_pipe_read(fd, &n, sizeof(int)) != sizeof(int)) goto DISASTER;
     if (n < 0) break;
     while (hn < n)
       {
@@ -837,14 +837,14 @@ if (f.system_filtering)
     int type;
     if (!rda_read_string(fd, &s)) goto DISASTER;
     if (!s) break;
-    if (read(fd, &type, sizeof(type)) != sizeof(type)) goto DISASTER;
+    if (os_pipe_read(fd, &type, sizeof(type)) != sizeof(type)) goto DISASTER;
     header_add(type, "%s", s);
     }
   }
 
 /* Read the values of the $n variables */
 
-if (read(fd, filter_n, sizeof(filter_n)) != sizeof(filter_n)) goto DISASTER;
+if (os_pipe_read(fd, filter_n, sizeof(filter_n)) != sizeof(filter_n)) goto DISASTER;
 
 /* If the yield is DELIVERED, NOTDELIVERED, FAIL, or FREEZE there may follow
 addresses and data to go with them. Keep them in the same order in the
@@ -875,10 +875,10 @@ if (yield == FF_DELIVERED || yield == FF_NOTDELIVERED ||
 
     /* Next comes the mode and the flags fields */
 
-    if (  read(fd, &addr->mode, sizeof(addr->mode)) != sizeof(addr->mode)
-       || read(fd, &addr->flags, sizeof(addr->flags)) != sizeof(addr->flags)
+    if (  os_pipe_read(fd, &addr->mode, sizeof(addr->mode)) != sizeof(addr->mode)
+       || os_pipe_read(fd, &addr->flags, sizeof(addr->flags)) != sizeof(addr->flags)
        || !rda_read_string(fd, &addr->prop.errors_address)
-       || read(fd, &i, sizeof(i)) != sizeof(i)
+       || os_pipe_read(fd, &i, sizeof(i)) != sizeof(i)
        )
       goto DISASTER;
     addr->prop.ignore_error = (i != 0);
@@ -907,7 +907,7 @@ if (yield == FF_DELIVERED || yield == FF_NOTDELIVERED ||
 
     /* Then an int containing reply options; zero => no reply data. */
 
-    if (read(fd, &reply_options, sizeof(int)) != sizeof(int)) goto DISASTER;
+    if (os_pipe_read(fd, &reply_options, sizeof(int)) != sizeof(int)) goto DISASTER;
     if ((reply_options & REPLY_EXISTS) != 0)
       {
       addr->reply = store_get(sizeof(reply_item), FALSE);
@@ -915,9 +915,9 @@ if (yield == FF_DELIVERED || yield == FF_NOTDELIVERED ||
       addr->reply->file_expand = (reply_options & REPLY_EXPAND) != 0;
       addr->reply->return_message = (reply_options & REPLY_RETURN) != 0;
 
-      if (read(fd,&(addr->reply->expand_forbid),sizeof(int)) !=
+      if (os_pipe_read(fd,&(addr->reply->expand_forbid),sizeof(int)) !=
             sizeof(int) ||
-          read(fd,&(addr->reply->once_repeat),sizeof(time_t)) !=
+          os_pipe_read(fd,&(addr->reply->once_repeat),sizeof(time_t)) !=
             sizeof(time_t) ||
           !rda_read_string(fd, &(addr->reply->to)) ||
           !rda_read_string(fd, &(addr->reply->cc)) ||
index 14bd91cdb3e2160c0ee47f65a2c2a8e302e07cc0..c4f3745096205ab29b300667b0bc14e6e53a1ac1 100644 (file)
@@ -1254,16 +1254,24 @@ if ((write_pid = fork()) == 0)
   rc = internal_transport_write_message(tctx, size_limit);
 
   save_errno = errno;
-  if (  write(pfd[pipe_write], (void *)&rc, sizeof(BOOL))
-        != sizeof(BOOL)
-     || write(pfd[pipe_write], (void *)&save_errno, sizeof(int))
-        != sizeof(int)
-     || write(pfd[pipe_write], (void *)&tctx->addr->more_errno, sizeof(int))
-        != sizeof(int)
-     || write(pfd[pipe_write], (void *)&tctx->addr->delivery_usec, sizeof(int))
-        != sizeof(int)
-     )
-    rc = FALSE;        /* compiler quietening */
+  errno = 0;
+  for (int retries = 10;;)
+    {
+    if (  os_pipe_write(pfd[pipe_write], (void *)&rc, sizeof(BOOL))
+         != sizeof(BOOL)
+       || os_pipe_write(pfd[pipe_write], (void *)&save_errno, sizeof(int))
+         != sizeof(int)
+       || os_pipe_write(pfd[pipe_write], (void *)&tctx->addr->more_errno, sizeof(int))
+         != sizeof(int)
+       || os_pipe_write(pfd[pipe_write], (void *)&tctx->addr->delivery_usec, sizeof(int))
+         != sizeof(int)
+       )
+      if (errno == EINTR && --retries > 0)
+       continue;
+      else
+       rc = FALSE;     /* compiler quietening */
+    break;
+    }
   exim_underbar_exit(0);
   }
 save_errno = errno;
@@ -1376,7 +1384,7 @@ if (write_pid > 0)
     if (rc == 0)
       {
       BOOL ok;
-      if (read(pfd[pipe_read], (void *)&ok, sizeof(BOOL)) != sizeof(BOOL))
+      if (os_pipe_read(pfd[pipe_read], (void *)&ok, sizeof(BOOL)) != sizeof(BOOL))
        {
        DEBUG(D_transport)
          debug_printf("pipe read from writing process: %s\n", strerror(errno));
@@ -1385,9 +1393,9 @@ if (write_pid > 0)
        }
       else if (!ok)
         {
-       int dummy = read(pfd[pipe_read], (void *)&save_errno, sizeof(int));
-        dummy = read(pfd[pipe_read], (void *)&tctx->addr->more_errno, sizeof(int));
-        dummy = read(pfd[pipe_read], (void *)&tctx->addr->delivery_usec, sizeof(int));
+       int dummy = os_pipe_read(pfd[pipe_read], (void *)&save_errno, sizeof(int));
+        dummy = os_pipe_read(pfd[pipe_read], (void *)&tctx->addr->more_errno, sizeof(int));
+        dummy = os_pipe_read(pfd[pipe_read], (void *)&tctx->addr->delivery_usec, sizeof(int));
        dummy = dummy;          /* compiler quietening */
         yield = FALSE;
         }