aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagnus Hagander <magnus@hagander.net>2017-01-04 10:48:30 +0100
committerMagnus Hagander <magnus@hagander.net>2017-01-04 10:48:30 +0100
commit9951741bbeb3ec37ca50e9ce3df1808c931ff6a6 (patch)
treeb9bc81ce0e1eb5c6b7d88562abbe308477ca15e3
parent9a4d51077c96c10322582211781bb969b51822ff (diff)
downloadpostgresql-9951741bbeb3ec37ca50e9ce3df1808c931ff6a6.tar.gz
postgresql-9951741bbeb3ec37ca50e9ce3df1808c931ff6a6.zip
Attempt to handle pending-delete files on Windows
These files are deleted but not yet gone from the filesystem. Operations on them will return ERROR_DELETE_PENDING. With this we start treating that as ENOENT, meaning files does not exist (which is the state it will soon reach). This should be safe in every case except when we try to recreate a file with exactly the same name. This is an operation that PostgreSQL does very seldom, so hopefully that won't happen much -- and even if it does, this treatment should be no worse than treating it as an unhandled error. We've been un able to reproduce the bug reliably, so pushing this to master to get buildfarm coverage and other testing. Once it's proven to be stable, it should be considered for backpatching. Discussion: https://postgr.es/m/20160712083220.1426.58667%40wrigleys.postgresql.org Patch by me and Michael Paquier
-rw-r--r--src/port/dirmod.c15
-rw-r--r--src/port/win32error.c3
2 files changed, 18 insertions, 0 deletions
diff --git a/src/port/dirmod.c b/src/port/dirmod.c
index 3db82e32ea9..08835962be6 100644
--- a/src/port/dirmod.c
+++ b/src/port/dirmod.c
@@ -372,7 +372,22 @@ pgwin32_safestat(const char *path, struct stat * buf)
r = stat(path, buf);
if (r < 0)
+ {
+ if (GetLastError() == ERROR_DELETE_PENDING)
+ {
+ /*
+ * File has been deleted, but is not gone from the filesystem
+ * yet. This can happen when some process with FILE_SHARE_DELETE
+ * has it open and it will be fully removed once that handle
+ * is closed. Meanwhile, we can't open it, so indicate that
+ * the file just doesn't exist.
+ */
+ errno = ENOENT;
+ return -1;
+ }
+
return r;
+ }
if (!GetFileAttributesEx(path, GetFileExInfoStandard, &attr))
{
diff --git a/src/port/win32error.c b/src/port/win32error.c
index 91095ee19a7..40655962a87 100644
--- a/src/port/win32error.c
+++ b/src/port/win32error.c
@@ -161,6 +161,9 @@ static const struct
},
{
ERROR_NOT_ENOUGH_QUOTA, ENOMEM
+ },
+ {
+ ERROR_DELETE_PENDING, ENOENT
}
};