diff --git a/Projects/Server.Tests/Tests/Timer/TimerTests.cs b/Projects/Server.Tests/Tests/Timer/TimerTests.cs index 9f610de50..e7a9b6241 100644 --- a/Projects/Server.Tests/Tests/Timer/TimerTests.cs +++ b/Projects/Server.Tests/Tests/Timer/TimerTests.cs @@ -85,6 +85,30 @@ public class TimerTests Assert.Equal(2, timerTicks.ExecutedCount); } + [Fact] + public void ClearAllTimers_StopsEveryTimerInASlot() + { + Timer.Init(0); + + var timers = new Timer[3]; + for (var i = 0; i < timers.Length; i++) + { + timers[i] = Timer.DelayCall(TimeSpan.FromMilliseconds(80), () => Assert.Fail("cleared timer fired")); + } + + Timer.ClearAllTimers(0); + + for (var i = 0; i < timers.Length; i++) + { + Assert.False(timers[i].Running); + } + + for (var tick = 8; tick <= 160; tick += 8) + { + Timer.Slice(tick); + } + } + private class TimerTicks { public long ExpectedTicks; diff --git a/Projects/Server/Timer/Timer.TimerWheel.cs b/Projects/Server/Timer/Timer.TimerWheel.cs index 2ab3ce547..0395bf3fe 100644 --- a/Projects/Server/Timer/Timer.TimerWheel.cs +++ b/Projects/Server/Timer/Timer.TimerWheel.cs @@ -321,13 +321,14 @@ public partial class Timer for (var i = 0; i < _ringSize; i++) { var node = t[i]; - Timer next; - do + while (node != null) { - next = node?._nextTimer; - node?.Stop(); - } while (next != null); + // Stop() unlinks the node, so read its successor first. + var next = node._nextTimer; + node.Stop(); + node = next; + } } } }