Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commit45f9d08

Browse files
committed
Fix race condition with unprotected use of a latch pointer variable.
Commit597a87c introduced a latch pointer variable to replace useof a long-lived shared latch in the shared WalRcvData structure.This was not well thought out, because there are now hazards of thepointer variable changing while it's being inspected by anotherprocess. This could obviously lead to a core dump in code likeif (WalRcv->latch)SetLatch(WalRcv->latch);and there's a more remote risk of a torn read, if we have anyplatforms where reading/writing a pointer is not atomic.An actual problem would occur only if the walreceiver processexits (gracefully) while the startup process is trying tosignal it, but that seems well within the realm of possibility.To fix, treat the pointer variable (not the referenced latch)as being protected by the WalRcv->mutex spinlock. Thereremains a race condition that we could apply SetLatch to aprocess latch that no longer belongs to the walreceiver, butI believe that's harmless: at worst it'd cause an extra wakeupof the next process to use that PGPROC structure.Back-patch to v10 where the faulty code was added.Discussion:https://postgr.es/m/22735.1507048202@sss.pgh.pa.us
1 parent89e434b commit45f9d08

File tree

3 files changed

+27
-16
lines changed

3 files changed

+27
-16
lines changed

‎src/backend/replication/walreceiver.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,13 +256,14 @@ WalReceiverMain(void)
256256
walrcv->lastMsgSendTime=
257257
walrcv->lastMsgReceiptTime=walrcv->latestWalEndTime=now;
258258

259+
/* Report the latch to use to awaken this process */
260+
walrcv->latch=&MyProc->procLatch;
261+
259262
SpinLockRelease(&walrcv->mutex);
260263

261264
/* Arrange to clean up at walreceiver exit */
262265
on_shmem_exit(WalRcvDie,0);
263266

264-
walrcv->latch=&MyProc->procLatch;
265-
266267
/* Properly accept or ignore signals the postmaster might send us */
267268
pqsignal(SIGHUP,WalRcvSigHupHandler);/* set flag to read config file */
268269
pqsignal(SIGINT,SIG_IGN);
@@ -777,8 +778,7 @@ WalRcvDie(int code, Datum arg)
777778
/* Ensure that all WAL records received are flushed to disk */
778779
XLogWalRcvFlush(true);
779780

780-
walrcv->latch=NULL;
781-
781+
/* Mark ourselves inactive in shared memory */
782782
SpinLockAcquire(&walrcv->mutex);
783783
Assert(walrcv->walRcvState==WALRCV_STREAMING||
784784
walrcv->walRcvState==WALRCV_RESTARTING||
@@ -789,6 +789,7 @@ WalRcvDie(int code, Datum arg)
789789
walrcv->walRcvState=WALRCV_STOPPED;
790790
walrcv->pid=0;
791791
walrcv->ready_to_display= false;
792+
walrcv->latch=NULL;
792793
SpinLockRelease(&walrcv->mutex);
793794

794795
/* Terminate the connection gracefully. */
@@ -1344,9 +1345,15 @@ ProcessWalSndrMessage(XLogRecPtr walEnd, TimestampTz sendTime)
13441345
void
13451346
WalRcvForceReply(void)
13461347
{
1348+
Latch*latch;
1349+
13471350
WalRcv->force_reply= true;
1348-
if (WalRcv->latch)
1349-
SetLatch(WalRcv->latch);
1351+
/* fetching the latch pointer might not be atomic, so use spinlock */
1352+
SpinLockAcquire(&WalRcv->mutex);
1353+
latch=WalRcv->latch;
1354+
SpinLockRelease(&WalRcv->mutex);
1355+
if (latch)
1356+
SetLatch(latch);
13501357
}
13511358

13521359
/*

‎src/backend/replication/walreceiverfuncs.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo,
226226
WalRcvData*walrcv=WalRcv;
227227
boollaunch= false;
228228
pg_time_tnow= (pg_time_t)time(NULL);
229+
Latch*latch;
229230

230231
/*
231232
* We always start at the beginning of the segment. That prevents a broken
@@ -274,12 +275,14 @@ RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo,
274275
walrcv->receiveStart=recptr;
275276
walrcv->receiveStartTLI=tli;
276277

278+
latch=walrcv->latch;
279+
277280
SpinLockRelease(&walrcv->mutex);
278281

279282
if (launch)
280283
SendPostmasterSignal(PMSIGNAL_START_WALRECEIVER);
281-
elseif (walrcv->latch)
282-
SetLatch(walrcv->latch);
284+
elseif (latch)
285+
SetLatch(latch);
283286
}
284287

285288
/*

‎src/include/replication/walreceiver.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,6 @@ typedef struct
117117
/* set true once conninfo is ready to display (obfuscated pwds etc) */
118118
boolready_to_display;
119119

120-
slock_tmutex;/* locks shared variables shown above */
121-
122-
/*
123-
* force walreceiver reply? This doesn't need to be locked; memory
124-
* barriers for ordering are sufficient.
125-
*/
126-
boolforce_reply;
127-
128120
/*
129121
* Latch used by startup process to wake up walreceiver after telling it
130122
* where to start streaming (after setting receiveStart and
@@ -133,6 +125,15 @@ typedef struct
133125
* normally mapped to procLatch when walreceiver is running.
134126
*/
135127
Latch*latch;
128+
129+
slock_tmutex;/* locks shared variables shown above */
130+
131+
/*
132+
* force walreceiver reply? This doesn't need to be locked; memory
133+
* barriers for ordering are sufficient. But we do need atomic fetch and
134+
* store semantics, so use sig_atomic_t.
135+
*/
136+
sig_atomic_tforce_reply;/* used as a bool */
136137
}WalRcvData;
137138

138139
externWalRcvData*WalRcv;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp