From: Junio C Hamano Date: Tue, 19 Jul 2016 20:22:14 +0000 (-0700) Subject: Merge branch 'sb/submodule-parallel-fetch' X-Git-Tag: v2.10.0-rc0~112 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/7725bebe21dfa4877dad74b1ac3d921f26f949cf?ds=inline;hp=-c Merge branch 'sb/submodule-parallel-fetch' 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 --- 7725bebe21dfa4877dad74b1ac3d921f26f949cf diff --combined wrapper.c index 5dc4e15aa9,a774ab7d80..26db215f0c --- a/wrapper.c +++ b/wrapper.c @@@ -152,9 -152,6 +152,9 @@@ void *xcalloc(size_t nmemb, size_t size { void *ret; + if (unsigned_mult_overflows(nmemb, size)) + die("data too large to fit into virtual memory space"); + memory_limit_check(size * nmemb, 0); ret = calloc(nmemb, size); if (!ret && (!nmemb || !size)) @@@ -227,6 -224,24 +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 -257,8 +260,8 @@@ ssize_t xread(int fd, void *buf, size_ 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 -276,13 +279,13 @@@ ssize_t xwrite(int fd, const void *buf 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; } } @@@ -394,19 -402,6 +405,19 @@@ FILE *xfdopen(int fd, const char *mode return stream; } +FILE *fopen_for_writing(const char *path) +{ + FILE *ret = fopen(path, "w"); + + if (!ret && errno == EPERM) { + if (!unlink(path)) + ret = fopen(path, "w"); + else + errno = EPERM; + } + return ret; +} + int xmkstemp(char *template) { int fd; @@@ -446,6 -441,23 +457,6 @@@ int git_mkstemp(char *path, size_t len return mkstemp(path); } -/* git_mkstemps() - create tmp file with suffix honoring TMPDIR variable. */ -int git_mkstemps(char *path, size_t len, const char *template, int suffix_len) -{ - const char *tmp; - size_t n; - - tmp = getenv("TMPDIR"); - if (!tmp) - tmp = "/tmp"; - n = snprintf(path, len, "%s/%s", tmp, template); - if (len <= n) { - errno = ENAMETOOLONG; - return -1; - } - return mkstemps(path, suffix_len); -} - /* Adapted from libiberty's mkstemp.c. */ #undef TMP_MAX @@@ -555,7 -567,7 +566,7 @@@ static int warn_if_unremovable(const ch if (!rc || errno == ENOENT) return 0; err = errno; - warning("unable to %s %s: %s", op, file, strerror(errno)); + warning_errno("unable to %s %s", op, file); errno = err; return rc; } @@@ -591,7 -603,7 +602,7 @@@ int remove_or_warn(unsigned int mode, c void warn_on_inaccessible(const char *path) { - warning(_("unable to access '%s': %s"), path, strerror(errno)); + warning_errno(_("unable to access '%s'"), path); } static int access_error_is_ok(int err, unsigned flag) @@@ -616,6 -628,18 +627,6 @@@ int access_or_die(const char *path, in return ret; } -struct passwd *xgetpwuid_self(void) -{ - struct passwd *pw; - - errno = 0; - pw = getpwuid(getuid()); - if (!pw) - die(_("unable to look up current user in the passwd file: %s"), - errno ? strerror(errno) : _("no such user")); - return pw; -} - char *xgetcwd(void) { struct strbuf sb = STRBUF_INIT;