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

Commit49a3360

Browse files
committed
Fix ordering of operations in SyncRepWakeQueue to avoid assertion failure.
Commit14e8803 removed the locking in SyncRepWaitForLSN, but thatintroduced a race condition, where SyncRepWaitForLSN might seesyncRepState already set to SYNC_REP_WAIT_COMPLETE, but the process wasnot yet removed from the queue. That tripped the assertion, that theprocess should no longer be in the uqeue. Reorder the operations inSyncRepWakeQueue to remove the process from the queue first, and updatesyncRepState only after that, and add a memory barrier in between to makesure the operations are made visible to other processes in that order.Fixes bug #14721 reported by Const Zhang. Analysis and fix by Thomas Munro.Backpatch down to 9.5, where the locking was removed.Discussion:https://www.postgresql.org/message-id/20170629023623.1480.26508%40wrigleys.postgresql.org
1 parent09ed6c7 commit49a3360

File tree

1 file changed

+16
-6
lines changed

1 file changed

+16
-6
lines changed

‎src/backend/replication/syncrep.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,11 @@ SyncRepWaitForLSN(XLogRecPtr lsn, bool commit)
293293
* WalSender has checked our LSN and has removed us from queue. Clean up
294294
* state and leave. It's OK to reset these shared memory fields without
295295
* holding SyncRepLock, because any walsenders will ignore us anyway when
296-
* we're not on the queue.
296+
* we're not on the queue. We need a read barrier to make sure we see
297+
* the changes to the queue link (this might be unnecessary without
298+
* assertions, but better safe than sorry).
297299
*/
300+
pg_read_barrier();
298301
Assert(SHMQueueIsDetached(&(MyProc->syncRepLinks)));
299302
MyProc->syncRepState=SYNC_REP_NOT_WAITING;
300303
MyProc->waitLSN=0;
@@ -1022,15 +1025,22 @@ SyncRepWakeQueue(bool all, int mode)
10221025
offsetof(PGPROC,syncRepLinks));
10231026

10241027
/*
1025-
* Set state to complete; see SyncRepWaitForLSN() for discussion of
1026-
* the various states.
1028+
* Remove thisproc from queue.
10271029
*/
1028-
thisproc->syncRepState=SYNC_REP_WAIT_COMPLETE;
1030+
SHMQueueDelete(&(thisproc->syncRepLinks));
10291031

10301032
/*
1031-
* Remove thisproc from queue.
1033+
* SyncRepWaitForLSN() reads syncRepState without holding the lock, so
1034+
* make sure that it sees the queue link being removed before the
1035+
* syncRepState change.
10321036
*/
1033-
SHMQueueDelete(&(thisproc->syncRepLinks));
1037+
pg_write_barrier();
1038+
1039+
/*
1040+
* Set state to complete; see SyncRepWaitForLSN() for discussion of
1041+
* the various states.
1042+
*/
1043+
thisproc->syncRepState=SYNC_REP_WAIT_COMPLETE;
10341044

10351045
/*
10361046
* Wake only when we have set state and removed from queue.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp