Make sure we don't count down past 0 QT_FATAL_CRITICALS
The old code first checked for == 0, then, if false, executed a fetchAndAdd(-1), both with relaxed memory ordering. This can lead to executions that, counter to what the code comment states, can count down past 0: // T1 T2 loadRelaxed() // true loadRelaxed() // true fetchAndAddRelaxed(-1) // e.g. 1 → 0 fetchAndAddRelaxed(-1) // 0 → -1 while fatality is detected exactly once, this execution doesn't stop at 0 and causes further calls to isFatal() to count down further, with the (very) remote spectre of underflow past INT_MIN. Fix by using a CAS loop instead, so each count-down uses only one step, not two, which therefore can no longer interleave. Fixes: QTBUG-115062 Change-Id: If77b906c94cb4b9fa91bfad84fe63bc8d9103b0a Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> (cherry picked from commit b933a5668cc5647d26378f8a9a52901d0497585d) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
63428b1f1f
commit
c9fe146401
@ -188,7 +188,11 @@ static bool is_fatal_count_down(QAtomicInt &n)
|
||||
{
|
||||
// it's fatal if the current value is exactly 1,
|
||||
// otherwise decrement if it's non-zero
|
||||
return n.loadRelaxed() && n.fetchAndAddRelaxed(-1) == 1;
|
||||
|
||||
int v = n.loadRelaxed();
|
||||
while (v != 0 && !n.testAndSetRelaxed(v, v - 1, v))
|
||||
;
|
||||
return v == 1; // we exited the loop, so either v == 0 or CAS succeeded to set n from v to v-1
|
||||
}
|
||||
|
||||
static bool isFatal(QtMsgType msgType)
|
||||
|
Loading…
x
Reference in New Issue
Block a user