about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2016-07-28 11:26:02 -0700
committerJunio C Hamano <gitster@pobox.com>2016-07-28 11:26:02 -0700
commit8e4571e57a1a3cc6f1318b3da8612b2e3c8e1252 (patch)
tree62c096209932596087c620dc7057378534895e27
parentc81d2836753a268be07346d362ffab3c6a5e14a9 (diff)
parentd751dd11ae16fd4e2410d3a32c8e2d951fafc923 (diff)
downloadgit-svn-8e4571e57a1a3cc6f1318b3da8612b2e3c8e1252.tar.gz
Fix recently introduced codepaths that are involved in parallel
submodule operations, which gave up on reading too early, and
could have wasted CPU while attempting to write under a corner
case condition.

* sb/submodule-parallel-fetch:
  hoist out handle_nonblock function for xread and xwrite
  xwrite: poll on non-blocking FDs
  xread: retry after poll on EAGAIN/EWOULDBLOCK
-rw-r--r--wrapper.c43
1 files changed, 27 insertions, 16 deletions
diff --git a/wrapper.c b/wrapper.c
index 5dc4e15aa9..26db215f0c 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -227,6 +227,24 @@ int xopen(const char *path, int oflag, ...)
         }
 }
 
+static int handle_nonblock(int fd, short poll_events, int err)
+{
+        struct pollfd pfd;
+
+        if (err != EAGAIN && err != EWOULDBLOCK)
+                return 0;
+
+        pfd.fd = fd;
+        pfd.events = poll_events;
+
+        /*
+         * no need to check for errors, here;
+         * a subsequent read/write will detect unrecoverable errors
+         */
+        poll(&pfd, 1, -1);
+        return 1;
+}
+
 /*
  * xread() is the same a read(), but it automatically restarts read()
  * operations with a recoverable error (EAGAIN and EINTR). xread()
@@ -242,20 +260,8 @@ ssize_t xread(int fd, void *buf, size_t len)
                 if (nr < 0) {
                         if (errno == EINTR)
                                 continue;
-                        if (errno == EAGAIN || errno == EWOULDBLOCK) {
-                                struct pollfd pfd;
-                                pfd.events = POLLIN;
-                                pfd.fd = fd;
-                                /*
-                                 * it is OK if this poll() failed; we
-                                 * want to leave this infinite loop
-                                 * only when read() returns with
-                                 * success, or an expected failure,
-                                 * which would be checked by the next
-                                 * call to read(2).
-                                 */
-                                poll(&pfd, 1, -1);
-                        }
+                        if (handle_nonblock(fd, POLLIN, errno))
+                                continue;
                 }
                 return nr;
         }
@@ -273,8 +279,13 @@ ssize_t xwrite(int fd, const void *buf, size_t len)
             len = MAX_IO_SIZE;
         while (1) {
                 nr = write(fd, buf, len);
-                if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
-                        continue;
+                if (nr < 0) {
+                        if (errno == EINTR)
+                                continue;
+                        if (handle_nonblock(fd, POLLOUT, errno))
+                                continue;
+                }
+
                 return nr;
         }
 }