]> granicus.if.org Git - postgresql/commitdiff
shm_mq: Fix detach race condition.
authorRobert Haas <rhaas@postgresql.org>
Mon, 5 Mar 2018 20:12:49 +0000 (15:12 -0500)
committerRobert Haas <rhaas@postgresql.org>
Mon, 5 Mar 2018 20:12:49 +0000 (15:12 -0500)
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

src/backend/storage/ipc/shm_mq.c

index 40df8e1251e48e09f951b85bf2ad2ede8a22847b..3faace249ff0b98d6cd0792cede824b0289192a9 100644 (file)
@@ -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