Commit 2873a862 by Jan Melcher

Retry renaming files on Access Denied errors

When a file is open for reading (without shared-delete permission), and
then a different thread/process called p_rename, that would fail, even
if the file was only open for reading for a few milliseconds. This
change lets p_rename wait up to 50ms for the file to be closed by the
reader. Applies only to win32.

This is especially important for git_filebuf_commit, because writes
should not fail if the file is read simultaneously.

Fixes #2207
parent 041fad4a
...@@ -467,10 +467,31 @@ int p_rename(const char *from, const char *to) ...@@ -467,10 +467,31 @@ int p_rename(const char *from, const char *to)
{ {
git_win32_path wfrom; git_win32_path wfrom;
git_win32_path wto; git_win32_path wto;
int rename_tries;
int rename_succeeded;
int error;
git_win32_path_from_c(wfrom, from); git_win32_path_from_c(wfrom, from);
git_win32_path_from_c(wto, to); git_win32_path_from_c(wto, to);
return MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? 0 : -1;
/* wait up to 50ms if file is locked by another thread or process */
rename_tries = 0;
rename_succeeded = 0;
while (rename_tries < 10) {
if (MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) != 0) {
rename_succeeded = 1;
break;
}
error = GetLastError();
if (error == ERROR_SHARING_VIOLATION || error == ERROR_ACCESS_DENIED) {
Sleep(5);
rename_tries++;
} else
break;
}
return rename_succeeded ? 0 : -1;
} }
int p_recv(GIT_SOCKET socket, void *buffer, size_t length, int flags) int p_recv(GIT_SOCKET socket, void *buffer, size_t length, int flags)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment