Skip to content

Commit 419113d

Browse files
committed
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>
1 parent 4531022 commit 419113d

File tree

1 file changed

+18
-13
lines changed

1 file changed

+18
-13
lines changed

src/backend/storage/ipc/dsm_impl.c

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,7 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
671671
{
672672
DWORD size_high;
673673
DWORD size_low;
674+
DWORD errcode;
674675

675676
/* Shifts >= the width of the type are undefined. */
676677
#ifdef _WIN64
@@ -686,27 +687,31 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size,
686687
size_high, /* Upper 32 bits of size */
687688
size_low, /* Lower 32 bits of size */
688689
name);
690+
691+
errcode = GetLastError();
692+
if (errcode == ERROR_ALREADY_EXISTS || errcode == ERROR_ACCESS_DENIED)
693+
{
694+
/*
695+
* On Windows, when the segment already exists, a handle for the
696+
* existing segment is returned. We must close it before
697+
* returning. However, if the existing segment is created by a
698+
* service, then it returns ERROR_ACCESS_DENIED. We don't do
699+
* _dosmaperr here, so errno won't be modified.
700+
*/
701+
if (hmap)
702+
CloseHandle(hmap);
703+
return false;
704+
}
705+
689706
if (!hmap)
690707
{
691-
_dosmaperr(GetLastError());
708+
_dosmaperr(errcode);
692709
ereport(elevel,
693710
(errcode_for_dynamic_shared_memory(),
694711
errmsg("could not create shared memory segment \"%s\": %m",
695712
name)));
696713
return false;
697714
}
698-
_dosmaperr(GetLastError());
699-
if (errno == EEXIST)
700-
{
701-
/*
702-
* On Windows, when the segment already exists, a handle for the
703-
* existing segment is returned. We must close it before
704-
* returning. We don't do _dosmaperr here, so errno won't be
705-
* modified.
706-
*/
707-
CloseHandle(hmap);
708-
return false;
709-
}
710715
}
711716
else
712717
{

0 commit comments

Comments
 (0)