Skip to content

Commit cfb2a4c

Browse files
committed
On Windows, wait a little to see if ERROR_ACCESS_DENIED goes away.
Attempting to open a file fails with ERROR_ACCESS_DENIED if the file is flagged for deletion but not yet actually gone (another in a long list of reasons why Windows is broken, if you ask me). This seems likely to explain a lot of irreproducible failures we see in the buildfarm. This state generally persists for only a millisecond or so, so just wait a bit and retry. If it's a real permissions problem, we'll eventually give up and report it as such. If it's the pending deletion case, we'll see file-not-found and report that after the deletion completes, and the caller will treat that in an appropriate way. In passing, rejigger the existing retry logic for some other error cases so that we don't uselessly wait an extra time when we're not going to retry anymore. Alexander Lakhin (with cosmetic tweaks by me). Back-patch to all supported branches, since this seems like a pretty safe change and the problem is definitely real. Discussion: https://postgr.es/m/16161-7a985d2f1bbe8f71@postgresql.org
1 parent 6aa1263 commit cfb2a4c

File tree

1 file changed

+22
-5
lines changed

1 file changed

+22
-5
lines changed

src/port/open.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,17 +95,14 @@ pgwin32_open(const char *fileName, int fileFlags,...)
9595
{
9696
/*
9797
* Sharing violation or locking error can indicate antivirus, backup
98-
* or similar software that's locking the file. Try again for 30
99-
* seconds before giving up.
98+
* or similar software that's locking the file. Wait a bit and try
99+
* again, giving up after 30 seconds.
100100
*/
101101
DWORD err = GetLastError();
102102

103103
if (err == ERROR_SHARING_VIOLATION ||
104104
err == ERROR_LOCK_VIOLATION)
105105
{
106-
pg_usleep(100000);
107-
loops++;
108-
109106
#ifndef FRONTEND
110107
if (loops == 50)
111108
ereport(LOG,
@@ -116,7 +113,27 @@ pgwin32_open(const char *fileName, int fileFlags,...)
116113
#endif
117114

118115
if (loops < 300)
116+
{
117+
pg_usleep(100000);
118+
loops++;
119+
continue;
120+
}
121+
}
122+
123+
/*
124+
* ERROR_ACCESS_DENIED can be returned if the file is deleted but not
125+
* yet gone (Windows NT status code is STATUS_DELETE_PENDING). Wait a
126+
* bit and try again, giving up after 1 second (since this condition
127+
* should never persist very long).
128+
*/
129+
if (err == ERROR_ACCESS_DENIED)
130+
{
131+
if (loops < 10)
132+
{
133+
pg_usleep(100000);
134+
loops++;
119135
continue;
136+
}
120137
}
121138

122139
_dosmaperr(err);

0 commit comments

Comments
 (0)