Amends commit b933a5668cc5647d26378f8a9a52901d0497585d ("Make sure we
don't count down past 0 QT_FATAL_CRITICALS"), which introduced the CAS.
Apparently it was a design decision then that only one thread would call
qAbort(), while the others would happily continue. For example, for the
common case of QT_FATAL_WARNINGS=1:
// T1 T2
v = n.loadRelaxed() // v = 1
v != 0 // true
n.testAndSet(v, v - 1, v) // n = 0
v = n.loadRelaxed() // v = 0
v != 0 // false
return v == 1; // false
This commit changes that design, for two reasons. First, a semantic one:
if one thread has detected a fatal condition, it must be equally fatal
for all threads. Second, we must accept a meaningful time between the
detected condition and the call to qAbort() and thus the time until its
effects take. In the worst case scenario, T1 could get suspended
indefinitely, at which point T2 having concluded that warnings weren't
fatal will happily execute forever. [This could happen *because* of
having called abort(), and though that's a SW bug elsewhere, we should
not let our other warnings and criticals continue.]
The fix is simple: we never decrement from 1. That way, if multiple
threads start their verification at the same time, they will all see the
value 1 and will all abort. The abort() standard library function is
thread-safe, as our replacements for it.
Pick-to: 6.5 6.8 6.9
Change-Id: I03fbcbac26bd1f34d631fffd43bb9c27d51783d0
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>