* WalSender has checked our LSN and has removed us from queue. Clean up
* state and leave. It's OK to reset these shared memory fields without
* holding SyncRepLock, because any walsenders will ignore us anyway when
- * we're not on the queue.
+ * we're not on the queue. We need a read barrier to make sure we see
+ * the changes to the queue link (this might be unnecessary without
+ * assertions, but better safe than sorry).
*/
+ pg_read_barrier();
Assert(SHMQueueIsDetached(&(MyProc->syncRepLinks)));
MyProc->syncRepState = SYNC_REP_NOT_WAITING;
MyProc->waitLSN = 0;
offsetof(PGPROC, syncRepLinks));
/*
- * Set state to complete; see SyncRepWaitForLSN() for discussion of
- * the various states.
+ * Remove thisproc from queue.
*/
- thisproc->syncRepState = SYNC_REP_WAIT_COMPLETE;
+ SHMQueueDelete(&(thisproc->syncRepLinks));
/*
- * Remove thisproc from queue.
+ * SyncRepWaitForLSN() reads syncRepState without holding the lock, so
+ * make sure that it sees the queue link being removed before the
+ * syncRepState change.
*/
- SHMQueueDelete(&(thisproc->syncRepLinks));
+ pg_write_barrier();
+
+ /*
+ * Set state to complete; see SyncRepWaitForLSN() for discussion of
+ * the various states.
+ */
+ thisproc->syncRepState = SYNC_REP_WAIT_COMPLETE;
/*
* Wake only when we have set state and removed from queue.