From 327fe5536a508963a68e8aded6dbb83effd68933 Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Tue, 9 Jul 2019 20:48:06 +1200 Subject: [PATCH 2/3] Forward received condition variable signals on cancel. After a process decides not to wait for a condition variable, it can still consume a signal before it reaches ConditionVariableSleep(). In that case, pass the signal on to another waiter if possible, so that a signal doesn't go missing when there is another process waiting that should receive it. Author: Thomas Munro Discussion: https://postgr.es/m/CA%2BhUKGLQ_RW%2BXs8znDn36e-%2Bmq2--zrPemBqTQ8eKT-VO1OF4Q%40mail.gmail.com --- src/backend/storage/lmgr/condition_variable.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/backend/storage/lmgr/condition_variable.c b/src/backend/storage/lmgr/condition_variable.c index 951039da551..c22522beeb8 100644 --- a/src/backend/storage/lmgr/condition_variable.c +++ b/src/backend/storage/lmgr/condition_variable.c @@ -246,6 +246,7 @@ void ConditionVariableCancelSleep(void) { ConditionVariable *cv = cv_sleep_target; + bool signaled = false; if (cv == NULL) return; @@ -253,8 +254,18 @@ ConditionVariableCancelSleep(void) SpinLockAcquire(&cv->mutex); if (proclist_contains(&cv->wakeup, MyProc->pgprocno, cvWaitLink)) proclist_delete(&cv->wakeup, MyProc->pgprocno, cvWaitLink); + else + signaled = true; SpinLockRelease(&cv->mutex); + /* + * If we've received a signal, pass it on to another waiting process, if + * there is one. Otherwise a call to ConditionVariableSignal() might get + * lost, despite there being another process ready to handle it. + */ + if (signaled) + ConditionVariableSignal(cv); + cv_sleep_target = NULL; } -- 2.21.0