win32: introduce `do_with_retries` macro Provide a macro that will allow us to run a function with posix-like return values multiple times in a retry loop, with an optional cleanup function called between invocations.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
diff --git a/include/git2/errors.h b/include/git2/errors.h
index 3b746b7..71bff0f 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -53,6 +53,7 @@ typedef enum {
GIT_PASSTHROUGH = -30, /**< Internal only */
GIT_ITEROVER = -31, /**< Signals end of iteration with iterator */
+ GIT_RETRY = -32, /**< Internal only */
} git_error_code;
/**
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c
index 14f30eb..1dd6bff 100644
--- a/src/win32/posix_w32.c
+++ b/src/win32/posix_w32.c
@@ -157,6 +157,27 @@ GIT_INLINE(void) set_errno(void)
}
}
+GIT_INLINE(bool) last_error_retryable(void)
+{
+ int os_error = GetLastError();
+
+ return (os_error == ERROR_SHARING_VIOLATION ||
+ os_error == ERROR_ACCESS_DENIED);
+}
+
+#define do_with_retries(fn, cleanup) \
+ do { \
+ int __tries, __ret; \
+ for (__tries = 0; __tries < 10; __tries++) { \
+ if (__tries && (__ret = (cleanup)) != 0) \
+ return __ret; \
+ if ((__ret = (fn)) != GIT_RETRY) \
+ return __ret; \
+ Sleep(5); \
+ } \
+ return -1; \
+ } while (0) \
+
/**
* Truncate or extend file.
*