summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2017-07-18 14:44:29 -0700
committerEdward Thomson <ethomson@edwardthomson.com>2017-07-26 10:41:03 +0100
commitbc35fd4b03fc770b574088969dabf07243510cfb (patch)
treed20670b04c3705387823f5e15c5f1118d51c311e
parent192a87e1fe68099beceaa2c8674a7a2e6587f2e7 (diff)
downloadlibgit2-ethomson/win32_remediate.tar.gz
win32: provide fast-path for retrying filesystem operationsethomson/win32_remediate
When using the `do_with_retries` macro for retrying filesystem operations in the posix emulation layer, allow the remediation function to return `GIT_RETRY`, meaning that the error was believed to be remediated, and the operation should be retried immediately, without a sleep. This is a slightly more general solution to the problem fixed in #4312.
-rw-r--r--src/win32/posix_w32.c20
1 files changed, 9 insertions, 11 deletions
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c
index 32fafa8ed..e744f4ffb 100644
--- a/src/win32/posix_w32.c
+++ b/src/win32/posix_w32.c
@@ -162,12 +162,15 @@ GIT_INLINE(bool) last_error_retryable(void)
#define do_with_retries(fn, remediation) \
do { \
- int __tries, __ret; \
- for (__tries = 0; __tries < git_win32__retries; __tries++) { \
- if (__tries && (__ret = (remediation)) != 0) \
- return __ret; \
+ int __retry, __ret; \
+ for (__retry = git_win32__retries; __retry; __retry--) { \
if ((__ret = (fn)) != GIT_RETRY) \
return __ret; \
+ if (__retry > 1 && (__ret = (remediation)) != 0) { \
+ if (__ret == GIT_RETRY) \
+ continue; \
+ return __ret; \
+ } \
Sleep(5); \
} \
return -1; \
@@ -186,7 +189,7 @@ static int ensure_writable(wchar_t *path)
if (!SetFileAttributesW(path, (attrs & ~FILE_ATTRIBUTE_READONLY)))
goto on_error;
- return 0;
+ return GIT_RETRY;
on_error:
set_errno();
@@ -243,11 +246,6 @@ GIT_INLINE(int) unlink_once(const wchar_t *path)
if (DeleteFileW(path))
return 0;
- set_errno();
-
- if (errno == EACCES && ensure_writable(path) == 0 && DeleteFileW(path))
- return 0;
-
if (last_error_retryable())
return GIT_RETRY;
@@ -262,7 +260,7 @@ int p_unlink(const char *path)
if (git_win32_path_from_utf8(wpath, path) < 0)
return -1;
- do_with_retries(unlink_once(wpath), 0);
+ do_with_retries(unlink_once(wpath), ensure_writable(wpath));
}
int p_fsync(int fd)