diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c index b7e512978315aea0f28a509d5c64fea8ecf54ced..b4ca75ea2f319a813781370abbe1185159f0478e 100644 --- a/src/backend/storage/ipc/latch.c +++ b/src/backend/storage/ipc/latch.c @@ -643,6 +643,9 @@ AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch, event->fd = fd; event->events = events; event->user_data = user_data; +#ifdef WIN32 + event->reset = false; +#endif if (events == WL_LATCH_SET) { @@ -1389,6 +1392,18 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, DWORD rc; WaitEvent *cur_event; + /* Reset any wait events that need it */ + for (cur_event = set->events; + cur_event < (set->events + set->nevents); + cur_event++) + { + if (cur_event->reset) + { + WaitEventAdjustWin32(set, cur_event); + cur_event->reset = false; + } + } + /* * Sleep. * @@ -1472,6 +1487,18 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, { /* data available in socket */ occurred_events->events |= WL_SOCKET_READABLE; + + /*------ + * WaitForMultipleObjects doesn't guarantee that a read event will + * be returned if the latch is set at the same time. Even if it + * did, the caller might drop that event expecting it to reoccur + * on next call. So, we must force the event to be reset if this + * WaitEventSet is used again in order to avoid an indefinite + * hang. Refer https://msdn.microsoft.com/en-us/library/windows/desktop/ms741576(v=vs.85).aspx + * for the behavior of socket events. + *------ + */ + cur_event->reset = true; } if ((cur_event->events & WL_SOCKET_WRITEABLE) && (resEvents.lNetworkEvents & FD_WRITE)) diff --git a/src/include/storage/latch.h b/src/include/storage/latch.h index e96e88f2faa3221cf9533989b35f59694b8737dd..8f5bd515ad6f0b0a834177b8c5ede615b2132b54 100644 --- a/src/include/storage/latch.h +++ b/src/include/storage/latch.h @@ -133,6 +133,9 @@ typedef struct WaitEvent uint32 events; /* triggered events */ pgsocket fd; /* socket fd associated with event */ void *user_data; /* pointer provided in AddWaitEventToSet */ +#ifdef WIN32 + bool reset; /* Is reset of the event required? */ +#endif } WaitEvent; /* forward declaration to avoid exposing latch.c implementation details */