summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera2020-04-29 00:39:04 +0000
committerAlvaro Herrera2020-04-29 00:39:04 +0000
commitd0abe78d84274cc203f3d117b8006dc2164ca31a (patch)
tree34df7310c6f1c9ca08b2df1aceb414d1255ed65c
parent52b164c5a00095a34685e66bf64b009578b9cfda (diff)
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 c6550776394e, 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]
-rw-r--r--contrib/test_decoding/expected/slot.out3
-rw-r--r--src/backend/replication/logical/logicalfuncs.c13
-rw-r--r--src/backend/replication/slotfuncs.c4
-rw-r--r--src/backend/replication/walsender.c14
4 files changed, 31 insertions, 3 deletions
diff --git a/contrib/test_decoding/expected/slot.out b/contrib/test_decoding/expected/slot.out
index 1000171530f..ea72bf9f157 100644
--- a/contrib/test_decoding/expected/slot.out
+++ b/contrib/test_decoding/expected/slot.out
@@ -143,7 +143,8 @@ SELECT slot_name FROM pg_create_physical_replication_slot('regression_slot3');
SELECT pg_replication_slot_advance('regression_slot3', '0/0'); -- invalid LSN
ERROR: invalid target WAL LSN
SELECT pg_replication_slot_advance('regression_slot3', '0/1'); -- error
-ERROR: cannot advance replication slot that has not previously reserved WAL
+ERROR: replication slot "regression_slot3" cannot be advanced
+DETAIL: This slot has never previously reserved WAL, or has been invalidated.
SELECT pg_drop_replication_slot('regression_slot3');
pg_drop_replication_slot
--------------------------
diff --git a/src/backend/replication/logical/logicalfuncs.c b/src/backend/replication/logical/logicalfuncs.c
index f5384f1df8c..fded8e82908 100644
--- a/src/backend/replication/logical/logicalfuncs.c
+++ b/src/backend/replication/logical/logicalfuncs.c
@@ -237,6 +237,19 @@ pg_logical_slot_get_changes_guts(FunctionCallInfo fcinfo, bool confirm, bool bin
LogicalOutputPrepareWrite,
LogicalOutputWrite, NULL);
+ /*
+ * After the sanity checks in CreateDecodingContext, make sure the
+ * restart_lsn is valid. Avoid "cannot get changes" wording in this
+ * errmsg because that'd be confusingly ambiguous about no changes
+ * being available.
+ */
+ if (XLogRecPtrIsInvalid(MyReplicationSlot->data.restart_lsn))
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("can no longer get changes from replication slot \"%s\"",
+ NameStr(*name)),
+ errdetail("This slot has never previously reserved WAL, or has been invalidated.")));
+
MemoryContextSwitchTo(oldcontext);
/*
diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c
index f776de3df7a..ae751e94e76 100644
--- a/src/backend/replication/slotfuncs.c
+++ b/src/backend/replication/slotfuncs.c
@@ -598,7 +598,9 @@ pg_replication_slot_advance(PG_FUNCTION_ARGS)
if (XLogRecPtrIsInvalid(MyReplicationSlot->data.restart_lsn))
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("cannot advance replication slot that has not previously reserved WAL")));
+ errmsg("replication slot \"%s\" cannot be advanced",
+ NameStr(*slotname)),
+ errdetail("This slot has never previously reserved WAL, or has been invalidated.")));
/*
* Check if the slot is not moving backwards. Physical slots rely simply
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 6c87f6087ce..8b55bbfcb2e 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -600,6 +600,12 @@ StartReplication(StartReplicationCmd *cmd)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("cannot use a logical replication slot for physical replication")));
+
+ /*
+ * We don't need to verify the slot's restart_lsn here; instead we
+ * rely on the caller requesting the starting point to use. If the
+ * WAL segment doesn't exist, we'll fail later.
+ */
}
/*
@@ -1134,6 +1140,13 @@ StartLogicalReplication(StartReplicationCmd *cmd)
(void) ReplicationSlotAcquire(cmd->slotname, SAB_Error);
+ if (XLogRecPtrIsInvalid(MyReplicationSlot->data.restart_lsn))
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot read from logical replication slot \"%s\"",
+ cmd->slotname),
+ errdetail("This slot has been invalidated because it exceeded the maximum reserved size.")));
+
/*
* Force a disconnect, so that the decoding code doesn't need to care
* about an eventual switch from running in recovery, to running in a
@@ -1159,7 +1172,6 @@ StartLogicalReplication(StartReplicationCmd *cmd)
WalSndPrepareWrite, WalSndWriteData,
WalSndUpdateProgress);
-
WalSndSetState(WALSNDSTATE_CATCHUP);
/* Send a CopyBothResponse message, and start streaming */