Skip to content

Commit 4e2d5ef

Browse files
committed
On Windows, when a file is deleted and another process still has an open
file handle on it, the file goes into "pending deletion" state where it still shows up in directory listing, but isn't accessible otherwise. That confuses RemoveOldXLogFiles(), making it think that the file hasn't been archived yet, while it actually was, and it was deleted along with the .done file. Fix that by renaming the file with ".deleted" extension before deleting it. Also check the return value of rename() and unlink(), so that if the removal fails for any reason (e.g another process is holding the file locked), we don't delete the .done file until the WAL file is really gone. Backpatch to 8.2, which is the oldest version supported on Windows.
1 parent 3ab8b7f commit 4e2d5ef

File tree

1 file changed

+36
-2
lines changed
  • src/backend/access/transam

1 file changed

+36
-2
lines changed

src/backend/access/transam/xlog.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.351 2009/09/01 02:54:51 alvherre Exp $
10+
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.352 2009/09/10 09:42:10 heikki Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -3040,6 +3040,9 @@ RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr)
30403040
struct dirent *xlde;
30413041
char lastoff[MAXFNAMELEN];
30423042
char path[MAXPGPATH];
3043+
#ifdef WIN32
3044+
char newpath[MAXPGPATH];
3045+
#endif
30433046
struct stat statbuf;
30443047

30453048
/*
@@ -3103,10 +3106,41 @@ RemoveOldXlogFiles(uint32 log, uint32 seg, XLogRecPtr endptr)
31033106
else
31043107
{
31053108
/* No need for any more future segments... */
3109+
int rc;
3110+
31063111
ereport(DEBUG2,
31073112
(errmsg("removing transaction log file \"%s\"",
31083113
xlde->d_name)));
3109-
unlink(path);
3114+
3115+
#ifdef WIN32
3116+
/*
3117+
* On Windows, if another process (e.g another backend)
3118+
* holds the file open in FILE_SHARE_DELETE mode, unlink
3119+
* will succeed, but the file will still show up in
3120+
* directory listing until the last handle is closed.
3121+
* To avoid confusing the lingering deleted file for a
3122+
* live WAL file that needs to be archived, rename it
3123+
* before deleting it.
3124+
*
3125+
* If another process holds the file open without
3126+
* FILE_SHARE_DELETE flag, rename will fail. We'll try
3127+
* again at the next checkpoint.
3128+
*/
3129+
snprintf(newpath, MAXPGPATH, "%s.deleted", path);
3130+
if (rename(path, newpath) != 0)
3131+
ereport(ERROR,
3132+
(errcode_for_file_access(),
3133+
errmsg("could not rename old transaction log file \"%s\"",
3134+
path)));
3135+
rc = unlink(newpath);
3136+
#else
3137+
rc = unlink(path);
3138+
#endif
3139+
if (rc != 0)
3140+
ereport(ERROR,
3141+
(errcode_for_file_access(),
3142+
errmsg("could not remove old transaction log file \"%s\": %m",
3143+
path)));
31103144
CheckpointStats.ckpt_segs_removed++;
31113145
}
31123146

0 commit comments

Comments
 (0)