Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 614b7f1

Browse files
committed
Fix "invalid spinlock number: 0" error in pg_stat_wal_receiver.
Commit 2c8dd05 added the atomic variable writtenUpto into walreceiver's shared memory information. It's initialized only when walreceiver started up but could be read via pg_stat_wal_receiver view anytime, i.e., even before it's initialized. In the server built with --disable-atomics and --disable-spinlocks, this uninitialized atomic variable read could cause "invalid spinlock number: 0" error. This commit changed writtenUpto so that it's initialized at the postmaster startup, to avoid the uninitialized variable read via pg_stat_wal_receiver and fix the error. Also this commit moved the read of writtenUpto after the release of spinlock protecting walreceiver's shared variables. This is necessary to prevent new spinlock from being taken by atomic variable read while holding another spinlock, and to shorten the spinlock duration. This change leads writtenUpto not to be consistent with the other walreceiver's shared variables protected by a spinlock. But this is OK because writtenUpto should not be used for data integrity checks. Back-patch to v13 where commit 2c8dd05 introduced the bug. Author: Fujii Masao Reviewed-by: Michael Paquier, Thomas Munro, Andres Freund Discussion: https://postgr.es/m/7ef8708c-5b6b-edd3-2cf2-7783f1c7c175@oss.nttdata.com
1 parent eb42110 commit 614b7f1

File tree

4 files changed

+20
-2
lines changed

4 files changed

+20
-2
lines changed

src/backend/replication/walreceiver.c

+9-2
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ WalReceiverMain(void)
249249

250250
SpinLockRelease(&walrcv->mutex);
251251

252-
pg_atomic_init_u64(&WalRcv->writtenUpto, 0);
252+
pg_atomic_write_u64(&WalRcv->writtenUpto, 0);
253253

254254
/* Arrange to clean up at walreceiver exit */
255255
on_shmem_exit(WalRcvDie, 0);
@@ -1325,7 +1325,6 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS)
13251325
state = WalRcv->walRcvState;
13261326
receive_start_lsn = WalRcv->receiveStart;
13271327
receive_start_tli = WalRcv->receiveStartTLI;
1328-
written_lsn = pg_atomic_read_u64(&WalRcv->writtenUpto);
13291328
flushed_lsn = WalRcv->flushedUpto;
13301329
received_tli = WalRcv->receivedTLI;
13311330
last_send_time = WalRcv->lastMsgSendTime;
@@ -1345,6 +1344,14 @@ pg_stat_get_wal_receiver(PG_FUNCTION_ARGS)
13451344
if (pid == 0 || !ready_to_display)
13461345
PG_RETURN_NULL();
13471346

1347+
/*
1348+
* Read "writtenUpto" without holding a spinlock. Note that it may not be
1349+
* consistent with the other shared variables of the WAL receiver
1350+
* protected by a spinlock, but this should not be used for data integrity
1351+
* checks.
1352+
*/
1353+
written_lsn = pg_atomic_read_u64(&WalRcv->writtenUpto);
1354+
13481355
/* determine result type */
13491356
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
13501357
elog(ERROR, "return type must be a row type");

src/backend/replication/walreceiverfuncs.c

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ WalRcvShmemInit(void)
6363
MemSet(WalRcv, 0, WalRcvShmemSize());
6464
WalRcv->walRcvState = WALRCV_STOPPED;
6565
SpinLockInit(&WalRcv->mutex);
66+
pg_atomic_init_u64(&WalRcv->writtenUpto, 0);
6667
WalRcv->latch = NULL;
6768
}
6869
}

src/test/regress/expected/sysviews.out

+7
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ select count(*) = 1 as ok from pg_stat_wal;
8383
t
8484
(1 row)
8585

86+
-- We expect no walreceiver running in this test
87+
select count(*) = 0 as ok from pg_stat_wal_receiver;
88+
ok
89+
----
90+
t
91+
(1 row)
92+
8693
-- This is to record the prevailing planner enable_foo settings during
8794
-- a regression test run.
8895
select name, setting from pg_settings where name like 'enable%';

src/test/regress/sql/sysviews.sql

+3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ select count(*) >= 0 as ok from pg_prepared_xacts;
4040
-- There must be only one record
4141
select count(*) = 1 as ok from pg_stat_wal;
4242

43+
-- We expect no walreceiver running in this test
44+
select count(*) = 0 as ok from pg_stat_wal_receiver;
45+
4346
-- This is to record the prevailing planner enable_foo settings during
4447
-- a regression test run.
4548
select name, setting from pg_settings where name like 'enable%';

0 commit comments

Comments
 (0)