From f076ec514631034e081740291d069a1f20fbb0a1 Mon Sep 17 00:00:00 2001 From: Vignesh Date: Fri, 21 Mar 2025 18:24:48 +0530 Subject: [PATCH v2] Fix issue with file handle retention during CREATE DATABASE in pg_restore During upgrades, when pg_restore performs CREATE DATABASE, the bgwriter or checkpointer may flush buffers and hold a file handle for the table. This causes issues if the table needs to be re-created later (e.g., after a TRUNCATE command), especially on OSes like older versions of Windows, where unlinked files aren't fully removed until they are no longer open. This commit fixes the issue by checking for STATUS_DELETE_PENDING and calling WaitForProcSignalBarrier, ensuring that all smgr file descriptors are closed across all backends before retrying the file operation. --- src/backend/storage/smgr/md.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c index 2ccb0faceb5..a97afedafdd 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -31,10 +31,20 @@ #include "miscadmin.h" #include "pg_trace.h" #include "pgstat.h" + +#if defined(WIN32) && !defined(__CYGWIN__) +#include "port/win32ntdll.h" +#endif + #include "storage/aio.h" #include "storage/bufmgr.h" #include "storage/fd.h" #include "storage/md.h" + +#if defined(WIN32) && !defined(__CYGWIN__) +#include "storage/procsignal.h" +#endif + #include "storage/relfilelocator.h" #include "storage/smgr.h" #include "storage/sync.h" @@ -214,6 +224,9 @@ mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo) MdfdVec *mdfd; RelPathStr path; File fd; +#if defined(WIN32) && !defined(__CYGWIN__) + bool retryattempted = false; +#endif if (isRedo && reln->md_num_open_segs[forknum] > 0) return; /* created and opened already... */ @@ -235,6 +248,9 @@ mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo) path = relpath(reln->smgr_rlocator, forknum); +#if defined(WIN32) && !defined(__CYGWIN__) +retry: +#endif fd = PathNameOpenFile(path.str, _mdfd_open_flags() | O_CREAT | O_EXCL); if (fd < 0) @@ -245,6 +261,15 @@ mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo) fd = PathNameOpenFile(path.str, _mdfd_open_flags()); if (fd < 0) { +#if defined(WIN32) && !defined(__CYGWIN__) + if (!retryattempted && pg_RtlGetLastNtStatus() == STATUS_DELETE_PENDING) + { + retryattempted = true; + WaitForProcSignalBarrier(EmitProcSignalBarrier(PROCSIGNAL_BARRIER_SMGRRELEASE)); + goto retry; + } +#endif + /* be sure to report the error reported by create, not open */ errno = save_errno; ereport(ERROR, -- 2.43.0