Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ab9a14e

Browse files
committed
Fix WAL file replacement during cascading replication on Windows.
When the startup process restores a WAL file from the archive, it deletes any old file with the same name and renames the new file in its place. On Windows, however, when a file is deleted, it still lingers as long as a process holds a file handle open on it. With cascading replication, a walsender process can hold the old file open, so the rename() in the startup process would fail. To fix that, rename the old file to a temporary name, to make the original file name available for reuse, before deleting the old file.
1 parent 2e0cc1f commit ab9a14e

File tree

1 file changed

+27
-1
lines changed
  • src/backend/access/transam

1 file changed

+27
-1
lines changed

src/backend/access/transam/xlog.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2787,7 +2787,33 @@ XLogFileRead(XLogSegNo segno, int emode, TimeLineID tli,
27872787
XLogFilePath(xlogfpath, tli, segno);
27882788
if (stat(xlogfpath, &statbuf) == 0)
27892789
{
2790-
if (unlink(xlogfpath) != 0)
2790+
char oldpath[MAXPGPATH];
2791+
#ifdef WIN32
2792+
static unsigned int deletedcounter = 1;
2793+
/*
2794+
* On Windows, if another process (e.g a walsender process) holds
2795+
* the file open in FILE_SHARE_DELETE mode, unlink will succeed,
2796+
* but the file will still show up in directory listing until the
2797+
* last handle is closed, and we cannot rename the new file in its
2798+
* place until that. To avoid that problem, rename the old file to
2799+
* a temporary name first. Use a counter to create a unique
2800+
* filename, because the same file might be restored from the
2801+
* archive multiple times, and a walsender could still be holding
2802+
* onto an old deleted version of it.
2803+
*/
2804+
snprintf(oldpath, MAXPGPATH, "%s.deleted%u",
2805+
xlogfpath, deletedcounter++);
2806+
if (rename(xlogfpath, oldpath) != 0)
2807+
{
2808+
ereport(ERROR,
2809+
(errcode_for_file_access(),
2810+
errmsg("could not rename file \"%s\" to \"%s\": %m",
2811+
xlogfpath, oldpath)));
2812+
}
2813+
#else
2814+
strncpy(oldpath, xlogfpath, MAXPGPATH);
2815+
#endif
2816+
if (unlink(oldpath) != 0)
27912817
ereport(FATAL,
27922818
(errcode_for_file_access(),
27932819
errmsg("could not remove file \"%s\": %m",

0 commit comments

Comments
 (0)