Skip to content

Commit d0abe78

Browse files
committed
Check slot->restart_lsn validity in a few more places
Lack of these checks could cause visible misbehavior, including assertion failures. This was missed in commit c655077, whereby restart_lsn becomes invalid when the size limit is exceeded. Also reword some existing error messages, and add errdetail(), so that the reported errors all match in spirit. Author: Kyotaro Horiguchi <[email protected]> Reviewed-by: Álvaro Herrera <[email protected]> Discussion: https://postgr.es/m/[email protected]
1 parent 52b164c commit d0abe78

File tree

4 files changed

+31
-3
lines changed

4 files changed

+31
-3
lines changed

contrib/test_decoding/expected/slot.out

+2-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,8 @@ SELECT slot_name FROM pg_create_physical_replication_slot('regression_slot3');
143143
SELECT pg_replication_slot_advance('regression_slot3', '0/0'); -- invalid LSN
144144
ERROR: invalid target WAL LSN
145145
SELECT pg_replication_slot_advance('regression_slot3', '0/1'); -- error
146-
ERROR: cannot advance replication slot that has not previously reserved WAL
146+
ERROR: replication slot "regression_slot3" cannot be advanced
147+
DETAIL: This slot has never previously reserved WAL, or has been invalidated.
147148
SELECT pg_drop_replication_slot('regression_slot3');
148149
pg_drop_replication_slot
149150
--------------------------

src/backend/replication/logical/logicalfuncs.c

+13
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,19 @@ pg_logical_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm, bool bin
237237
LogicalOutputPrepareWrite,
238238
LogicalOutputWrite, NULL);
239239

240+
/*
241+
* After the sanity checks in CreateDecodingContext, make sure the
242+
* restart_lsn is valid. Avoid "cannot get changes" wording in this
243+
* errmsg because that'd be confusingly ambiguous about no changes
244+
* being available.
245+
*/
246+
if (XLogRecPtrIsInvalid(MyReplicationSlot->data.restart_lsn))
247+
ereport(ERROR,
248+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
249+
errmsg("can no longer get changes from replication slot \"%s\"",
250+
NameStr(*name)),
251+
errdetail("This slot has never previously reserved WAL, or has been invalidated.")));
252+
240253
MemoryContextSwitchTo(oldcontext);
241254

242255
/*

src/backend/replication/slotfuncs.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,9 @@ pg_replication_slot_advance(PG_FUNCTION_ARGS)
598598
if (XLogRecPtrIsInvalid(MyReplicationSlot->data.restart_lsn))
599599
ereport(ERROR,
600600
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
601-
errmsg("cannot advance replication slot that has not previously reserved WAL")));
601+
errmsg("replication slot \"%s\" cannot be advanced",
602+
NameStr(*slotname)),
603+
errdetail("This slot has never previously reserved WAL, or has been invalidated.")));
602604

603605
/*
604606
* Check if the slot is not moving backwards. Physical slots rely simply

src/backend/replication/walsender.c

+13-1
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,12 @@ StartReplication(StartReplicationCmd *cmd)
600600
ereport(ERROR,
601601
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
602602
errmsg("cannot use a logical replication slot for physical replication")));
603+
604+
/*
605+
* We don't need to verify the slot's restart_lsn here; instead we
606+
* rely on the caller requesting the starting point to use. If the
607+
* WAL segment doesn't exist, we'll fail later.
608+
*/
603609
}
604610

605611
/*
@@ -1134,6 +1140,13 @@ StartLogicalReplication(StartReplicationCmd *cmd)
11341140

11351141
(void) ReplicationSlotAcquire(cmd->slotname, SAB_Error);
11361142

1143+
if (XLogRecPtrIsInvalid(MyReplicationSlot->data.restart_lsn))
1144+
ereport(ERROR,
1145+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1146+
errmsg("cannot read from logical replication slot \"%s\"",
1147+
cmd->slotname),
1148+
errdetail("This slot has been invalidated because it exceeded the maximum reserved size.")));
1149+
11371150
/*
11381151
* Force a disconnect, so that the decoding code doesn't need to care
11391152
* about an eventual switch from running in recovery, to running in a
@@ -1159,7 +1172,6 @@ StartLogicalReplication(StartReplicationCmd *cmd)
11591172
WalSndPrepareWrite, WalSndWriteData,
11601173
WalSndUpdateProgress);
11611174

1162-
11631175
WalSndSetState(WALSNDSTATE_CATCHUP);
11641176

11651177
/* Send a CopyBothResponse message, and start streaming */

0 commit comments

Comments
 (0)