• Tom Lane's avatar
    Rewrite ConditionVariableBroadcast() to avoid live-lock. · aced5a92
    Tom Lane authored
    The original implementation of ConditionVariableBroadcast was, per its
    self-description, "the dumbest way possible".  Thomas Munro found out
    it was a bit too dumb.  An awakened process may immediately re-queue
    itself, if the specific condition it's waiting for is not yet satisfied.
    If this happens before ConditionVariableBroadcast is able to see the wait
    queue as empty, then ConditionVariableBroadcast will re-awaken the same
    process, repeating the cycle.  Given unlucky timing this back-and-forth
    can repeat indefinitely; loops lasting thousands of seconds have been
    seen in testing.
    
    To fix, add our own process to the end of the wait queue to serve as a
    sentinel, and exit the broadcast loop once our process is not there
    anymore.  There are various special considerations described in the
    comments, the principal disadvantage being that wakers can no longer
    be sure whether they awakened a real waiter or just a sentinel.  But in
    practice nobody pays attention to the result of ConditionVariableSignal
    or ConditionVariableBroadcast anyway, so that problem seems hypothetical.
    
    Back-patch to v10 where condition_variable.c was introduced.
    
    Tom Lane and Thomas Munro
    
    Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
    aced5a92
condition_variable.c 9.53 KB