summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2016-09-20 12:04:41 -0400
committerRobert Haas <rhaas@postgresql.org>2016-09-20 12:04:41 -0400
commit419113dfdc4c729f6c763cc30a9b02ee68a7da94 (patch)
tree7315c7f4b1e7e398a3acec68b2633db4b48ffa07 /src
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>
Diffstat (limited to 'src')
-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 99051f02c8c..7122c4abe00 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
{