1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-02 11:44:50 +03:00

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>
This commit is contained in:
Robert Haas 2016-09-20 12:04:41 -04:00
parent 45310221a9
commit 419113dfdc

View File

@ -671,6 +671,7 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
{ {
DWORD size_high; DWORD size_high;
DWORD size_low; DWORD size_low;
DWORD errcode;
/* Shifts >= the width of the type are undefined. */ /* Shifts >= the width of the type are undefined. */
#ifdef _WIN64 #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_high, /* Upper 32 bits of size */
size_low, /* Lower 32 bits of size */ size_low, /* Lower 32 bits of size */
name); name);
if (!hmap)
{ errcode = GetLastError();
_dosmaperr(GetLastError()); if (errcode == ERROR_ALREADY_EXISTS || errcode == ERROR_ACCESS_DENIED)
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 * On Windows, when the segment already exists, a handle for the
* existing segment is returned. We must close it before * existing segment is returned. We must close it before
* returning. We don't do _dosmaperr here, so errno won't be * returning. However, if the existing segment is created by a
* modified. * service, then it returns ERROR_ACCESS_DENIED. We don't do
* _dosmaperr here, so errno won't be modified.
*/ */
if (hmap)
CloseHandle(hmap); CloseHandle(hmap);
return false; 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;
}
} }
else else
{ {