Skip to content

Commit 4efe26c

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 0279f62 commit 4efe26c

File tree

1 file changed

+17
-2
lines changed

1 file changed

+17
-2
lines changed

src/backend/storage/ipc/shm_mq.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -501,11 +501,26 @@ shm_mq_receive(shm_mq_handle *mqh, Size *nbytesp, void **datap, bool nowait)
501501
{
502502
if (nowait)
503503
{
504+
int counterparty_gone;
505+
506+
/*
507+
* We shouldn't return at this point at all unless the sender
508+
* hasn't attached yet. However, the correct return value depends
509+
* on whether the sender is still attached. If we first test
510+
* whether the sender has ever attached and then test whether the
511+
* sender has detached, there's a race condition: a sender that
512+
* attaches and detaches very quickly might fool us into thinking
513+
* the sender never attached at all. So, test whether our
514+
* counterparty is definitively gone first, and only afterwards
515+
* check whether the sender ever attached in the first place.
516+
*/
517+
counterparty_gone = shm_mq_counterparty_gone(mq, mqh->mqh_handle);
504518
if (shm_mq_get_sender(mq) == NULL)
505519
{
506-
if (shm_mq_counterparty_gone(mq, mqh->mqh_handle))
520+
if (counterparty_gone)
507521
return SHM_MQ_DETACHED;
508-
return SHM_MQ_WOULD_BLOCK;
522+
else
523+
return SHM_MQ_WOULD_BLOCK;
509524
}
510525
}
511526
else if (!shm_mq_wait_internal(mq, &mq->mq_sender, mqh->mqh_handle)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy