mirror of
https://github.com/OPCFoundation/UA-.NETStandard.git
synced 2026-10-26 20:55:01 +08:00
RetryBudget: swap Reset() write order to avoid stale-tick race
Previous Reset(): Volatile.Write(ref m_started, 0); Interlocked.Exchange(ref m_startTicks, kNotStarted); A concurrent EnsureStarted() observer could see m_started == 0 (taking the "reset, so go start" branch), then read the stale m_startTicks value BEFORE the Interlocked.Exchange landed, and treat the budget as already-started against the pre-reset timestamp. IsExhausted / TryConsume then computed elapsed time from the old origin. Fix: reset m_startTicks first, then m_started. EnsureStarted writes m_started = 1 only after the CAS on m_startTicks succeeds, so resetting m_startTicks first preserves that invariant — no observer can see "started == 1" with a stale tick value.
This commit is contained in:
@@ -121,8 +121,12 @@ namespace Opc.Ua
|
||||
/// <inheritdoc/>
|
||||
public void Reset()
|
||||
{
|
||||
Volatile.Write(ref m_started, 0);
|
||||
// Order matters: clear m_startTicks BEFORE m_started so a concurrent
|
||||
// EnsureStarted observer cannot see "started=1" with a stale tick value.
|
||||
// EnsureStarted writes m_started=1 only after the CAS on m_startTicks
|
||||
// succeeds, so resetting m_startTicks first preserves that invariant.
|
||||
Interlocked.Exchange(ref m_startTicks, kNotStarted);
|
||||
Volatile.Write(ref m_started, 0);
|
||||
}
|
||||
|
||||
private long EnsureStarted()
|
||||
|
||||
Reference in New Issue
Block a user