Skip to content

Commit 038aa89

Browse files
committed
shm_mq: Third attempt at fixing nowait behavior in shm_mq_receive.
Commit a1480ec purported to fix the problems with commit b2ccb5f, 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.
1 parent 11e7f9d commit 038aa89

File tree

1 file changed

+17
-2
lines changed

1 file changed

+17
-2
lines changed

src/backend/storage/ipc/shm_mq.c

+17-2
Original file line numberDiff line numberDiff line change
@@ -405,11 +405,26 @@ shm_mq_receive(shm_mq_handle *mqh, Size *nbytesp, void **datap, bool nowait)
405405
{
406406
if (nowait)
407407
{
408+
int counterparty_gone;
409+
410+
/*
411+
* We shouldn't return at this point at all unless the sender
412+
* hasn't attached yet. However, the correct return value depends
413+
* on whether the sender is still attached. If we first test
414+
* whether the sender has ever attached and then test whether the
415+
* sender has detached, there's a race condition: a sender that
416+
* attaches and detaches very quickly might fool us into thinking
417+
* the sender never attached at all. So, test whether our
418+
* counterparty is definitively gone first, and only afterwards
419+
* check whether the sender ever attached in the first place.
420+
*/
421+
counterparty_gone = shm_mq_counterparty_gone(mq, mqh->mqh_handle);
408422
if (shm_mq_get_sender(mq) == NULL)
409423
{
410-
if (shm_mq_counterparty_gone(mq, mqh->mqh_handle))
424+
if (counterparty_gone)
411425
return SHM_MQ_DETACHED;
412-
return SHM_MQ_WOULD_BLOCK;
426+
else
427+
return SHM_MQ_WOULD_BLOCK;
413428
}
414429
}
415430
else if (!shm_mq_wait_internal(mq, &mq->mq_sender, mqh->mqh_handle)

0 commit comments

Comments
 (0)