On Linux we may receive EINTR if the read call is interrupted
before any data is read, if this is the case we can try to read
again.
---
 libutil/concat.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/libutil/concat.c b/libutil/concat.c
index 2e9aa52..5cbadd2 100644
--- a/libutil/concat.c
+++ b/libutil/concat.c
@@ -1,4 +1,5 @@
 /* See LICENSE file for copyright and license details. */
+#include <errno.h>
 #include <unistd.h>
 
 #include "../util.h"
@@ -9,15 +10,26 @@ concat(int f1, const char *s1, int f2, const char *s2)
        char buf[BUFSIZ];
        ssize_t n;
 
-       while ((n = read(f1, buf, sizeof(buf))) > 0) {
+       for (;;) {
+               n = read(f1, buf, sizeof(buf));
+
+               if (n == 0)
+                       break;
+
+               if (n < 0) {
+#ifdef __linux__
+                       if (errno == EINTR)
+                               continue;
+#endif
+                       weprintf("read %s:", s1);
+                       return -1;
+               }
+
                if (writeall(f2, buf, n) < 0) {
                        weprintf("write %s:", s2);
                        return -2;
                }
        }
-       if (n < 0) {
-               weprintf("read %s:", s1);
-               return -1;
-       }
+
        return 0;
 }
-- 
2.13.0


Reply via email to