mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-02-23 19:39:53 +08:00
shm_mq: Third attempt at fixing nowait behavior in shm_mq_receive.
Commita1480ec1d3
purported to fix the problems with commitb2ccb5f4e6
, 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.
This commit is contained in:
parent
0279f62fdc
commit
4efe26cbd3
@ -501,11 +501,26 @@ shm_mq_receive(shm_mq_handle *mqh, Size *nbytesp, void **datap, bool 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_counterparty_gone(mq, mqh->mqh_handle))
|
||||
if (counterparty_gone)
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user