Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1ke6Zf-0006lV-PA for pgsql-hackers@arkaria.postgresql.org; Sun, 15 Nov 2020 01:11:23 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1ke6Zd-0002hr-8p for pgsql-hackers@arkaria.postgresql.org; Sun, 15 Nov 2020 01:11:21 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1ke6Zc-0002hi-Th for pgsql-hackers@lists.postgresql.org; Sun, 15 Nov 2020 01:11:21 +0000 Received: from mail-il1-x135.google.com ([2607:f8b0:4864:20::135]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1ke6ZX-0001cQ-TQ for pgsql-hackers@postgresql.org; Sun, 15 Nov 2020 01:11:19 +0000 Received: by mail-il1-x135.google.com with SMTP id y9so11940714ilb.0 for ; Sat, 14 Nov 2020 17:11:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telsasoft-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=ByFTOkomm2aU2NaqNYDY/u8XHOG0ToQq67Mn4bkBhe8=; b=oAXDIZ3SzrKnKOhJ+Mz8WslB4M6DBEKotaBF2nm/zGsjfklXeBDIwrYfEAfCb1EzIP 0NijGL+DQ1wAgsFhhlzZB5qiC8teWjk8t04LAR3JY3Z66EMA8ooBHDmbn5XxoE8Ci38t IhHXa3S6Ig8uG5+7kGadKdylZ6SUvnumGptUnX+2WmFRMha/r2MlJVC212rbV/PeCR5I pJjUYj77gtGSqwB7owMyGdoOV0qlZuGC3qipptHf4ufm9WTpgVDyAbVfDQUJNW3x9sNK hBQFdj86SftqfL1nbYrGFTdHCi0XzNl+SU355PMCIIycHIWJpnSyUbYdowBQXFF1MiDy ysuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=ByFTOkomm2aU2NaqNYDY/u8XHOG0ToQq67Mn4bkBhe8=; b=sRpzf53FoxtGUNweEjvNG0a9P/MYsyHiioFlLaT326H9LpnhvySHwOR/kdV3GG1e8f v1DYrBG1HT/f1DhncarKWrnmD/hQOUNrqqsUBWpu3jxyRLsZJELKuO8aOi3zyRke7VEt CXzkh0gTQwCYftoLsplWPWR0lOn4zOM530P82AOjIVWI9eWNajI42bTma1Q5Cpit6M0R 18JqFkCca/b80uzWplxCQRG1bT3/Oa2Diywr2F3KeB+CRJ1q1qVHy1JUmNc45PMWvMPd 8rAL6+XknHgMjd43OxT9NQkizuAUUxaFi0ZdmSVL9hv4isE3m9deJD9JNKY8ipnZGcGS 8yEw== X-Gm-Message-State: AOAM5301xNkZdTYJarU+ymMs6phQGHmPmxBYLkTzNVBR60AtFC2tdKIg KGICjDyTX+B3hYPtGeRtzkVedA== X-Google-Smtp-Source: ABdhPJzalgVi3A5c5FXZL02ew8tGs2qJaGD6VlUhPU6Q02tS5W+tF4S6iQVwTHi41zUG2+oBHILzAA== X-Received: by 2002:a92:1f19:: with SMTP id i25mr4535787ile.198.1605402674469; Sat, 14 Nov 2020 17:11:14 -0800 (PST) Received: from pryzbyj.telsasoft (charmander.telsasoft.com. [50.244.222.1]) by smtp.gmail.com with ESMTPSA id a13sm7970047ilh.0.2020.11.14.17.11.13 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 14 Nov 2020 17:11:13 -0800 (PST) Received: by pryzbyj.telsasoft (Postfix, from userid 1000) id 02573800747; Sat, 14 Nov 2020 19:11:12 -0600 (CST) Date: Sat, 14 Nov 2020 19:11:12 -0600 From: Justin Pryzby To: Alexander Lakhin Cc: pgsql-hackers Subject: Re: More time spending with "delete pending" Message-ID: <20201115011112.GW30691@telsasoft.com> References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.9.4 (2018-02-28) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk On Sat, Nov 14, 2020 at 01:00:00PM +0300, Alexander Lakhin wrote: > As noted in [1], a sensible solution would be putting the same "retry on > ERROR_ACCESS_DENIED" action in a wrapper for stat(). > And bed90759f brought in master the _pgstat64() function, where such > error handling should be placed. > So please look at the patch (based on the previous one made to fix > bug#16161), that makes the attached test pass. Your patch introduces a "loops", but doesn't use it to escape the loop. > diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c > index d34182a7b0..922df49125 100644 > --- a/src/backend/utils/adt/genfile.c > +++ b/src/backend/utils/adt/genfile.c > @@ -28,6 +28,7 @@ > #include "funcapi.h" > #include "mb/pg_wchar.h" > #include "miscadmin.h" > +#include "port.h" > #include "postmaster/syslogger.h" > #include "storage/fd.h" > #include "utils/acl.h" > diff --git a/src/port/win32stat.c b/src/port/win32stat.c > index 4351aa4d08..c2b55c7fa6 100644 > --- a/src/port/win32stat.c > +++ b/src/port/win32stat.c > @@ -170,6 +170,7 @@ _pgstat64(const char *name, struct stat *buf) > SECURITY_ATTRIBUTES sa; > HANDLE hFile; > int ret; > + int loops = 0; > #if _WIN32_WINNT < 0x0600 > IO_STATUS_BLOCK ioStatus; > FILE_STANDARD_INFORMATION standardInfo; > @@ -182,31 +183,60 @@ _pgstat64(const char *name, struct stat *buf) > errno = EINVAL; > return -1; > } > - > /* fast not-exists check */ > if (GetFileAttributes(name) == INVALID_FILE_ATTRIBUTES) > { > - _dosmaperr(GetLastError()); > - return -1; > + DWORD err = GetLastError(); > + > + if (err != ERROR_ACCESS_DENIED) { > + _dosmaperr(err); > + return -1; > + } > } > > /* get a file handle as lightweight as we can */ > sa.nLength = sizeof(SECURITY_ATTRIBUTES); > sa.bInheritHandle = TRUE; > sa.lpSecurityDescriptor = NULL; > - hFile = CreateFile(name, > - GENERIC_READ, > - (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), > - &sa, > - OPEN_EXISTING, > - (FILE_FLAG_NO_BUFFERING | FILE_FLAG_BACKUP_SEMANTICS | > - FILE_FLAG_OVERLAPPED), > - NULL); > - if (hFile == INVALID_HANDLE_VALUE) > + while ((hFile = CreateFile(name, > + GENERIC_READ, > + (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), > + &sa, > + OPEN_EXISTING, > + (FILE_FLAG_NO_BUFFERING | FILE_FLAG_BACKUP_SEMANTICS | > + FILE_FLAG_OVERLAPPED), > + NULL)) == INVALID_HANDLE_VALUE) > { > DWORD err = GetLastError(); > > - CloseHandle(hFile); > + /* > + * ERROR_ACCESS_DENIED is returned if the file is deleted but not yet > + * gone (Windows NT status code is STATUS_DELETE_PENDING). In that > + * case we want to wait a bit and try again, giving up after 1 second > + * (since this condition should never persist very long). However, > + * there are other commonly-hit cases that return ERROR_ACCESS_DENIED, > + * so care is needed. In particular that happens if we try to open a > + * directory, or of course if there's an actual file-permissions > + * problem. To distinguish these cases, try a stat(). In the > + * delete-pending case, it will either also get STATUS_DELETE_PENDING, > + * or it will see the file as gone and fail with ENOENT. In other > + * cases it will usually succeed. The only somewhat-likely case where > + * this coding will uselessly wait is if there's a permissions problem > + * with a containing directory, which we hope will never happen in any > + * performance-critical code paths. > + */ > + if (err == ERROR_ACCESS_DENIED) > + { > + struct microsoft_native_stat st; > + > + if (microsoft_native_stat(name, &st) != 0) > + { > + pg_usleep(100000); > + loops++; > + continue; > + } > + } > + > _dosmaperr(err); > return -1; > }