Commit 4efe26cb authored by Robert Haas's avatar Robert Haas

shm_mq: Third attempt at fixing nowait behavior in shm_mq_receive.

Commit a1480ec1 purported to fix the
problems with commit b2ccb5f4, but it
didn't completely fix them.  The problem is that the checks were
performed in the wrong order, leading to a race condition.  If the
sender attached, sent a message, and detached after the receiver
called shm_mq_get_sender and before the receiver called
shm_mq_counterparty_gone, we'd incorrectly return SHM_MQ_DETACHED
before all messages were read.  Repair by reversing the order of
operations, and add a long comment explaining why this new logic is
(hopefully) correct.
parent 0279f62f
...@@ -501,11 +501,26 @@ shm_mq_receive(shm_mq_handle *mqh, Size *nbytesp, void **datap, bool nowait) ...@@ -501,11 +501,26 @@ shm_mq_receive(shm_mq_handle *mqh, Size *nbytesp, void **datap, bool nowait)
{ {
if (nowait) if (nowait)
{ {
int counterparty_gone;
/*
* We shouldn't return at this point at all unless the sender
* hasn't attached yet. However, the correct return value depends
* on whether the sender is still attached. If we first test
* whether the sender has ever attached and then test whether the
* sender has detached, there's a race condition: a sender that
* attaches and detaches very quickly might fool us into thinking
* the sender never attached at all. So, test whether our
* counterparty is definitively gone first, and only afterwards
* check whether the sender ever attached in the first place.
*/
counterparty_gone = shm_mq_counterparty_gone(mq, mqh->mqh_handle);
if (shm_mq_get_sender(mq) == NULL) if (shm_mq_get_sender(mq) == NULL)
{ {
if (shm_mq_counterparty_gone(mq, mqh->mqh_handle)) if (counterparty_gone)
return SHM_MQ_DETACHED; return SHM_MQ_DETACHED;
return SHM_MQ_WOULD_BLOCK; else
return SHM_MQ_WOULD_BLOCK;
} }
} }
else if (!shm_mq_wait_internal(mq, &mq->mq_sender, mqh->mqh_handle) else if (!shm_mq_wait_internal(mq, &mq->mq_sender, mqh->mqh_handle)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment