summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2020-05-15 19:05:40 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2020-05-15 19:05:40 -0400
commit594ba7f79d32ad1e915c3acb53d84b6e57884ce5 (patch)
treebd27d0976c302b5f9c495d4745e0ac5e25e90ab5
parent4649eb91916b9906fe2604af4c7157852700403f (diff)
Fix bogus initialization of replication origin shared memory state.
The previous coding zeroed out offsetof(ReplicationStateCtl, states) more bytes than it was entitled to, as a consequence of starting the zeroing from the wrong pointer (or, if you prefer, using the wrong calculation of how much to zero). It's unsurprising that this has not caused any reported problems, since it can be expected that the newly-allocated block is at the end of what we've used in shared memory, and we always make the shmem block substantially bigger than minimally necessary. Nonetheless, this is wrong and it could bite us someday; plus it's a dangerous model for somebody to copy. This dates back to the introduction of this code (commit 5aa235042), so back-patch to all supported branches.
-rw-r--r--src/backend/replication/logical/origin.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c
index 9fd962233e0..dd650cb4968 100644
--- a/src/backend/replication/logical/origin.c
+++ b/src/backend/replication/logical/origin.c
@@ -144,6 +144,7 @@ typedef struct ReplicationStateCtl
{
int tranche_id;
LWLockTranche tranche;
+ /* Array of length max_replication_slots */
ReplicationState states[FLEXIBLE_ARRAY_MEMBER];
} ReplicationStateCtl;
@@ -160,6 +161,10 @@ TimestampTz replorigin_session_origin_timestamp = 0;
* max_replication_slots?
*/
static ReplicationState *replication_states;
+
+/*
+ * Actual shared memory block (replication_states[] is now part of this).
+ */
static ReplicationStateCtl *replication_states_ctl;
/*
@@ -447,7 +452,7 @@ ReplicationOriginShmemSize(void)
/*
* XXX: max_replication_slots is arguably the wrong thing to use, as here
* we keep the replay state of *remote* transactions. But for now it seems
- * sufficient to reuse it, lest we introduce a separate guc.
+ * sufficient to reuse it, rather than introduce a separate GUC.
*/
if (max_replication_slots == 0)
return size;
@@ -477,6 +482,8 @@ ReplicationOriginShmemInit(void)
{
int i;
+ MemSet(replication_states_ctl, 0, ReplicationOriginShmemSize());
+
replication_states_ctl->tranche_id = LWTRANCHE_REPLICATION_ORIGIN;
replication_states_ctl->tranche.name = "replication_origin";
replication_states_ctl->tranche.array_base =
@@ -484,8 +491,6 @@ ReplicationOriginShmemInit(void)
replication_states_ctl->tranche.array_stride =
sizeof(ReplicationState);
- MemSet(replication_states, 0, ReplicationOriginShmemSize());
-
for (i = 0; i < max_replication_slots; i++)
LWLockInitialize(&replication_states[i].lock,
replication_states_ctl->tranche_id);