Skip to content

Commit 5c393a0

Browse files
committed
Fix volatile-safety issue in asyncQueueReadAllNotifications().
The "pos" variable is modified within PG_TRY and then referenced within PG_CATCH, so for strict POSIX conformance it must be marked volatile. Superficially the code looked safe because pos's address was taken, which was sufficient to force it into memory ... but it's not sufficient to ensure that the compiler applies updates exactly where the program text says to. The volatility marking has to extend into a couple of subroutines too, but I think that's probably a good thing because the risk of out-of-order updates is mostly in those subroutines not asyncQueueReadAllNotifications() itself. In principle the compiler could have re-ordered operations such that an error could be thrown while "pos" had an incorrect value. It's unclear how real the risk is here, but for safety back-patch to all active branches.
1 parent 502e5f9 commit 5c393a0

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

src/backend/commands/async.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -371,13 +371,13 @@ static void Exec_UnlistenAllCommit(void);
371371
static bool IsListeningOn(const char *channel);
372372
static void asyncQueueUnregister(void);
373373
static bool asyncQueueIsFull(void);
374-
static bool asyncQueueAdvance(QueuePosition *position, int entryLength);
374+
static bool asyncQueueAdvance(volatile QueuePosition *position, int entryLength);
375375
static void asyncQueueNotificationToEntry(Notification *n, AsyncQueueEntry *qe);
376376
static ListCell *asyncQueueAddEntries(ListCell *nextNotify);
377377
static void asyncQueueFillWarning(void);
378378
static bool SignalBackends(void);
379379
static void asyncQueueReadAllNotifications(void);
380-
static bool asyncQueueProcessPageEntries(QueuePosition *current,
380+
static bool asyncQueueProcessPageEntries(volatile QueuePosition *current,
381381
QueuePosition stop,
382382
char *page_buffer);
383383
static void asyncQueueAdvanceTail(void);
@@ -1204,7 +1204,7 @@ asyncQueueIsFull(void)
12041204
* returns true, else false.
12051205
*/
12061206
static bool
1207-
asyncQueueAdvance(QueuePosition *position, int entryLength)
1207+
asyncQueueAdvance(volatile QueuePosition *position, int entryLength)
12081208
{
12091209
int pageno = QUEUE_POS_PAGE(*position);
12101210
int offset = QUEUE_POS_OFFSET(*position);
@@ -1794,7 +1794,7 @@ DisableNotifyInterrupt(void)
17941794
static void
17951795
asyncQueueReadAllNotifications(void)
17961796
{
1797-
QueuePosition pos;
1797+
volatile QueuePosition pos;
17981798
QueuePosition oldpos;
17991799
QueuePosition head;
18001800
bool advanceTail;
@@ -1954,7 +1954,7 @@ asyncQueueReadAllNotifications(void)
19541954
* The QueuePosition *current is advanced past all processed messages.
19551955
*/
19561956
static bool
1957-
asyncQueueProcessPageEntries(QueuePosition *current,
1957+
asyncQueueProcessPageEntries(volatile QueuePosition *current,
19581958
QueuePosition stop,
19591959
char *page_buffer)
19601960
{

0 commit comments

Comments
 (0)