From fbaf30392aca794a667e21616138a544c264d17c Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Mon, 5 Mar 2018 09:44:49 +1300 Subject: [PATCH] Fix detach race condition in shm_mq.c. 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. Repair by reading the values in the correct order. Thomas Munro Discussion: https://postgr.es/m/CAEepm%3D2myZ4qxpt1a%3DC%2BwEv3o188K13K3UvD-44FK0SdAzHy%2Bw%40mail.gmail.com --- src/backend/storage/ipc/shm_mq.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/backend/storage/ipc/shm_mq.c b/src/backend/storage/ipc/shm_mq.c index 40df8e1251e..3e7ee758d3b 100644 --- a/src/backend/storage/ipc/shm_mq.c +++ b/src/backend/storage/ipc/shm_mq.c @@ -1020,6 +1020,15 @@ shm_mq_receive_bytes(shm_mq_handle *mqh, Size bytes_needed, bool nowait, { Size offset; uint64 read; + bool detached; + + /* + * Read the detached flag first and then insert a read barrier, to + * make sure that we read the final version of mq_bytes_written that + * was written before the flag was raised. + */ + detached = mq->mq_detached; + pg_read_barrier(); /* Get bytes written, so we can compute what's available to read. */ written = pg_atomic_read_u64(&mq->mq_bytes_written); @@ -1057,7 +1066,7 @@ shm_mq_receive_bytes(shm_mq_handle *mqh, Size bytes_needed, bool nowait, * receiving a message stored in the buffer even after the sender has * detached. */ - if (mq->mq_detached) + if (detached) return SHM_MQ_DETACHED; /* -- 2.16.2