From 419113dfdc4c729f6c763cc30a9b02ee68a7da94 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Tue, 20 Sep 2016 12:04:41 -0400 Subject: [PATCH] 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: --- src/backend/storage/ipc/dsm_impl.c | 33 +++++++++++++++++------------- 1 file changed, 19 insertions(+), 14 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,25 +687,29 @@ 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); - if (!hmap) - { - _dosmaperr(GetLastError()); - ereport(elevel, - (errcode_for_dynamic_shared_memory(), - errmsg("could not create shared memory segment \"%s\": %m", - name))); - return false; - } - _dosmaperr(GetLastError()); - if (errno == EEXIST) + + 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. We don't do _dosmaperr here, so errno won't be - * modified. + * 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. */ - CloseHandle(hmap); + if (hmap) + CloseHandle(hmap); + return false; + } + + if (!hmap) + { + _dosmaperr(errcode); + ereport(elevel, + (errcode_for_dynamic_shared_memory(), + errmsg("could not create shared memory segment \"%s\": %m", + name))); return false; } }