postgres.git / summary / log / commit / refs

commit    6d7547c219adf2436323cdbd4bebc5e872d53546
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Mon Dec 16 20:10:55 2019 +0000

    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


src/port/open.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/port/open.c b/src/port/open.c index f37afc75121..51652762a15 100644 --- a/src/port/open.c +++ b/src/port/open.c @@ -111,17 +111,14 @@ pgwin32_open(const char *fileName, int fileFlags,...) { /* * Sharing violation or locking error can indicate antivirus, backup - * or similar software that's locking the file. Try again for 30 - * seconds before giving up. + * or similar software that's locking the file. Wait a bit and try + * again, giving up after 30 seconds. */ DWORD err = GetLastError(); if (err == ERROR_SHARING_VIOLATION || err == ERROR_LOCK_VIOLATION) { - pg_usleep(100000); - loops++; - #ifndef FRONTEND if (loops == 50) ereport(LOG, @@ -132,7 +129,27 @@ pgwin32_open(const char *fileName, int fileFlags,...) #endif if (loops < 300) + { + pg_usleep(100000); + loops++; + continue; + } + } + + /* + * ERROR_ACCESS_DENIED can be returned if the file is deleted but not + * yet gone (Windows NT status code is STATUS_DELETE_PENDING). Wait a + * bit and try again, giving up after 1 second (since this condition + * should never persist very long). + */ + if (err == ERROR_ACCESS_DENIED) + { + if (loops < 10) + { + pg_usleep(100000); + loops++; continue; + } } _dosmaperr(err); [parent: 91fca4bb60e8]