From: Robert Haas Date: Mon, 5 Mar 2018 20:12:49 +0000 (-0500) Subject: shm_mq: Fix detach race condition. X-Git-Tag: REL_11_BETA1~653 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=42d7074ebb832e511d1edec8091cd474d169eef1;p=postgresql shm_mq: Fix detach race condition. Commit 34db06ef9a1d7f36391c64293bf1e0ce44a33915 adopted a lock-free design for shm_mq.c, but it introduced a race condition that could lose messages. When shm_mq_receive_bytes() detects that the other end has detached, it must make sure that it has seen the final version of mq_bytes_written, or it might miss a message sent before detaching. Thomas Munro Discussion: https://postgr.es/m/CAEepm%3D2myZ4qxpt1a%3DC%2BwEv3o188K13K3UvD-44FK0SdAzHy%2Bw%40mail.gmail.com --- diff --git a/src/backend/storage/ipc/shm_mq.c b/src/backend/storage/ipc/shm_mq.c index 40df8e1251..3faace249f 100644 --- a/src/backend/storage/ipc/shm_mq.c +++ b/src/backend/storage/ipc/shm_mq.c @@ -1058,7 +1058,19 @@ shm_mq_receive_bytes(shm_mq_handle *mqh, Size bytes_needed, bool nowait, * detached. */ if (mq->mq_detached) + { + /* + * If the writer advanced mq_bytes_written and then set + * mq_detached, we might not have read the final value of + * mq_bytes_written above. Insert a read barrier and then check + * again if mq_bytes_written has advanced. + */ + pg_read_barrier(); + if (written != pg_atomic_read_u64(&mq->mq_bytes_written)) + continue; + return SHM_MQ_DETACHED; + } /* * We didn't get enough data to satisfy the request, so mark any data