summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Haas2016-09-20 16:04:41 +0000
committerRobert Haas2016-09-20 16:04:41 +0000
commit419113dfdc4c729f6c763cc30a9b02ee68a7da94 (patch)
tree7315c7f4b1e7e398a3acec68b2633db4b48ffa07
parent45310221a9afccd98e78813459472370ade9dc4c (diff)
Retry DSM control segment creation if Windows indicates access denied.
Otherwise, attempts to run multiple postmasters running on the same machine may fail, because Windows sometimes returns ERROR_ACCESS_DENIED rather than ERROR_ALREADY_EXISTS when there is an existing segment. Hitting this bug is much more likely because of another defect not fixed by this patch, namely that dsm_postmaster_startup() uses random() which returns the same value every time. But that's not a reason not to fix this. Kyotaro Horiguchi and Amit Kapila, reviewed by Michael Paquier Discussion: <CAA4eK1JyNdMeF-dgrpHozDecpDfsRZUtpCi+1AbtuEkfG3YooQ@mail.gmail.com>
-rw-r--r--src/backend/storage/ipc/dsm_impl.c31
1 files changed, 18 insertions, 13 deletions
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index 99051f02c8..7122c4abe0 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -671,6 +671,7 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
{
DWORD size_high;
DWORD size_low;
+ DWORD errcode;
/* Shifts >= the width of the type are undefined. */
#ifdef _WIN64
@@ -686,27 +687,31 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
size_high, /* Upper 32 bits of size */
size_low, /* Lower 32 bits of size */
name);
+
+ errcode = GetLastError();
+ if (errcode == ERROR_ALREADY_EXISTS || errcode == ERROR_ACCESS_DENIED)
+ {
+ /*
+ * On Windows, when the segment already exists, a handle for the
+ * existing segment is returned. We must close it before
+ * returning. However, if the existing segment is created by a
+ * service, then it returns ERROR_ACCESS_DENIED. We don't do
+ * _dosmaperr here, so errno won't be modified.
+ */
+ if (hmap)
+ CloseHandle(hmap);
+ return false;
+ }
+
if (!hmap)
{
- _dosmaperr(GetLastError());
+ _dosmaperr(errcode);
ereport(elevel,
(errcode_for_dynamic_shared_memory(),
errmsg("could not create shared memory segment \"%s\": %m",
name)));
return false;
}
- _dosmaperr(GetLastError());
- if (errno == EEXIST)
- {
- /*
- * On Windows, when the segment already exists, a handle for the
- * existing segment is returned. We must close it before
- * returning. We don't do _dosmaperr here, so errno won't be
- * modified.
- */
- CloseHandle(hmap);
- return false;
- }
}
else
{