postgres.git / summary / log / commit / refs

commit    3cac0ec85992829c160bdd8a370dd4676d42f58c
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Sat Jan 06 00:42:49 2018 +0000
First released in: 11.0, 10.2

    Reorder steps in ConditionVariablePrepareToSleep for more safety.
    
    In the admittedly-very-unlikely case that AddWaitEventToSet fails,
    ConditionVariablePrepareToSleep would error out after already having
    set cv_sleep_target, which is probably bad, and after having already
    set cv_wait_event_set, which is very bad.  Transaction abort might or
    might not clean up cv_sleep_target properly; but there is nothing
    that would be aware that the WaitEventSet wasn't fully constructed,
    so that all future condition variable sleeps would be broken.
    We can easily guard against these hazards with slight restructuring.
    
    Back-patch to v10 where condition_variable.c was introduced.
    
    Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com


src/backend/storage/lmgr/condition_variable.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/backend/storage/lmgr/condition_variable.c b/src/backend/storage/lmgr/condition_variable.c index 55275cfafcb..cac3d36b6a3 100644 --- a/src/backend/storage/lmgr/condition_variable.c +++ b/src/backend/storage/lmgr/condition_variable.c @@ -54,6 +54,21 @@ ConditionVariablePrepareToSleep(ConditionVariable *cv) { int pgprocno = MyProc->pgprocno; + /* + * If first time through in this process, create a WaitEventSet, which + * we'll reuse for all condition variable sleeps. + */ + if (cv_wait_event_set == NULL) + { + WaitEventSet *new_event_set; + + new_event_set = CreateWaitEventSet(TopMemoryContext, 1); + AddWaitEventToSet(new_event_set, WL_LATCH_SET, PGINVALID_SOCKET, + MyLatch, NULL); + /* Don't set cv_wait_event_set until we have a correct WES. */ + cv_wait_event_set = new_event_set; + } + /* * It's not legal to prepare a sleep until the previous sleep has been * completed or canceled. @@ -63,14 +78,6 @@ ConditionVariablePrepareToSleep(ConditionVariable *cv) /* Record the condition variable on which we will sleep. */ cv_sleep_target = cv; - /* Create a reusable WaitEventSet. */ - if (cv_wait_event_set == NULL) - { - cv_wait_event_set = CreateWaitEventSet(TopMemoryContext, 1); - AddWaitEventToSet(cv_wait_event_set, WL_LATCH_SET, PGINVALID_SOCKET, - MyLatch, NULL); - } - /* * Reset my latch before adding myself to the queue and before entering * the caller's predicate loop. [parent: aced5a92bf46]