{"thread":{"id":"18961","subject":"[PATCH 1/2] Windows: Work around intermittent failures in mingw_rename","startedAt":"2009-04-20T08:01:37Z","lastAt":"2009-04-20T10:01:54Z","messageCount":2,"participants":["Johannes Sixt","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"111691","messageId":"49EC2BE1.9080200@viscovery.net","threadId":"18961","inReplyTo":null,"subject":"[PATCH 1/2] Windows: Work around intermittent failures in mingw_rename","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-04-20T08:01:37Z","receivedAt":"2009-04-20T08:01:37Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"From: Johannes Sixt <j6t@kdbg.org>\nDate: Fri, 3 Apr 2009 08:49:59 +0200\n\nWe have replaced rename() with a version that can rename a file to a\ndestination that already exists. Nevertheless, many users, the author\nincluded, observe failures in the code that are not reproducible.\n\nThe theory is that the failures are due to some other process that happens\nto have opened the destination file briefly at the wrong moment. (And there\nis no way on Windows to delete or replace a file that is currently open.)\nThe most likely candidate for such a process is a virus scanner. The\nfailure is more often observed while there is heavy git activity (for\nexample while the test suite is running or during a rebase operation).\n\nWe work around the failure by retrying the rename operation if it failed\ndue to ERROR_ACCESS_DENIED. The retries are delayed a bit: The first only\nby giving up the time slice, the next after the minimal scheduling\ngranularity, and if more retries are needed, then we wait some non-trivial\namount of time with exponential back-off.\n\nSigned-off-by: Johannes Sixt <j6t@kdbg.org>\n---\n Steffen, Dscho,\n\n this is slightly different from the version that is currently 4msysgit:\n I removed the warning that was printed when a retry was attempted.\n\n -- Hannes\n\n compat/mingw.c |   21 +++++++++++++++++++--\n 1 files changed, 19 insertions(+), 2 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 4b37d93..74eae20 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -978,7 +978,9 @@ int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)\n #undef rename\n int mingw_rename(const char *pold, const char *pnew)\n {\n-\tDWORD attrs;\n+\tDWORD attrs, gle;\n+\tint tries = 0;\n+\tstatic const int delay[] = { 0, 1, 10, 20, 40 };\n\n \t/*\n \t * Try native rename() first to get errno right.\n@@ -988,10 +990,12 @@ int mingw_rename(const char *pold, const char *pnew)\n \t\treturn 0;\n \tif (errno != EEXIST)\n \t\treturn -1;\n+repeat:\n \tif (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))\n \t\treturn 0;\n \t/* TODO: translate more errors */\n-\tif (GetLastError() == ERROR_ACCESS_DENIED &&\n+\tgle = GetLastError();\n+\tif (gle == ERROR_ACCESS_DENIED &&\n \t    (attrs = GetFileAttributes(pnew)) != INVALID_FILE_ATTRIBUTES) {\n \t\tif (attrs & FILE_ATTRIBUTE_DIRECTORY) {\n \t\t\terrno = EISDIR;\n@@ -1001,10 +1005,23 @@ int mingw_rename(const char *pold, const char *pnew)\n \t\t    SetFileAttributes(pnew, attrs & ~FILE_ATTRIBUTE_READONLY)) {\n \t\t\tif (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))\n \t\t\t\treturn 0;\n+\t\t\tgle = GetLastError();\n \t\t\t/* revert file attributes on failure */\n \t\t\tSetFileAttributes(pnew, attrs);\n \t\t}\n \t}\n+\tif (tries < ARRAY_SIZE(delay) && gle == ERROR_ACCESS_DENIED) {\n+\t\t/*\n+\t\t * We assume that some other process had the source or\n+\t\t * destination file open at the wrong moment and retry.\n+\t\t * In order to give the other process a higher chance to\n+\t\t * complete its operation, we give up our time slice now.\n+\t\t * If we have to retry again, we do sleep a bit.\n+\t\t */\n+\t\tSleep(delay[tries]);\n+\t\ttries++;\n+\t\tgoto repeat;\n+\t}\n \terrno = EACCES;\n \treturn -1;\n }\n-- \n1.6.3.rc1.989.ga175e.dirty\n"},{"id":"111706","messageId":"alpine.DEB.1.00.0904201201290.6955@intel-tinevez-2-302","threadId":"18961","inReplyTo":"49EC2BE1.9080200@viscovery.net","subject":"Re: [PATCH 1/2] Windows: Work around intermittent failures in mingw_rename","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-04-20T10:01:54Z","receivedAt":"2009-04-20T10:01:54Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 20 Apr 2009, Johannes Sixt wrote:\n\n>  this is slightly different from the version that is currently 4msysgit: \n>  I removed the warning that was printed when a retry was attempted.\n\nMakes sense.\n\nCiao,\nDscho\n"}]}