Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 0b54a80

Browse filesBrowse files
committed
Fix portability issues with parsing of recovery_target_xid
The parsing of this parameter has been using strtoul(), which is not portable across platforms. On most Unix platforms, unsigned long has a size of 64 bits, while on Windows it is 32 bits. It is common in recovery scenarios to rely on the output of txid_current() or even the newer pg_current_xact_id() to get a transaction ID for setting up recovery_target_xid. The value returned by those functions includes the epoch in the computed result, which would cause strtoul() to fail where unsigned long has a size of 32 bits once the epoch is incremented. WAL records and 2PC data include only information about 32-bit XIDs and it is not possible to have XIDs across more than one epoch, so discarding the high bits from the transaction ID set has no impact on recovery. On the contrary, the use of strtoul() prevents a consistent behavior across platforms depending on the size of unsigned long. This commit changes the parsing of recovery_target_xid to use pg_strtouint64() instead, available down to 9.6. There is one TAP test stressing recovery with recovery_target_xid, where a tweak based on pg_reset{xlog,wal} is added to bump the XID epoch so as this change gets tested, as per an idea from Alexander Lakhin. Reported-by: Alexander Lakhin Discussion: https://postgr.es/m/16780-107fd0c0385b1035@postgresql.org Backpatch-through: 9.6
1 parent 1d5f3f9 commit 0b54a80
Copy full SHA for 0b54a80

File tree

Expand file treeCollapse file tree

2 files changed

+5
-1
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+5
-1
lines changed

‎src/backend/access/transam/xlog.c

Copy file name to clipboardExpand all lines: src/backend/access/transam/xlog.c
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5162,7 +5162,7 @@ readRecoveryCommandFile(void)
51625162
else if (strcmp(item->name, "recovery_target_xid") == 0)
51635163
{
51645164
errno = 0;
5165-
recoveryTargetXid = (TransactionId) strtoul(item->value, NULL, 0);
5165+
recoveryTargetXid = (TransactionId) pg_strtouint64(item->value, NULL, 0);
51665166
if (errno == EINVAL || errno == ERANGE)
51675167
ereport(FATAL,
51685168
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),

‎src/test/recovery/t/003_recovery_targets.pl

Copy file name to clipboardExpand all lines: src/test/recovery/t/003_recovery_targets.pl
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ sub test_recovery_standby
5050
my $node_master = get_new_node('master');
5151
$node_master->init(has_archiving => 1, allows_streaming => 1);
5252

53+
# Bump the transaction ID epoch. This is useful to stress the portability
54+
# of recovery_target_xid parsing.
55+
system_or_bail('pg_resetxlog', '-e', '1', $node_master->data_dir);
56+
5357
# Start it
5458
$node_master->start;
5559

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.