From 285dd79a10ac5363ed0e579005c97af76aac7592 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Wed, 30 Oct 2013 21:50:36 +0100 Subject: [PATCH] [#1959] Proposed fix to correctly handle timeouts that overflow the ticks in the wheel --- .../java/io/netty/util/HashedWheelTimer.java | 5 +++-- .../io/netty/util/HashedWheelTimerTest.java | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/io/netty/util/HashedWheelTimer.java b/common/src/main/java/io/netty/util/HashedWheelTimer.java index 4a39914df8..0a2f26f91c 100644 --- a/common/src/main/java/io/netty/util/HashedWheelTimer.java +++ b/common/src/main/java/io/netty/util/HashedWheelTimer.java @@ -485,9 +485,10 @@ public class HashedWheelTimer implements Timer { this.task = task; this.deadline = deadline; - final long ticks = Math.max(deadline / tickDuration, tick); // Ensure we don't schedule for past. + long calculated = deadline / tickDuration; + final long ticks = Math.max(calculated, tick); // Ensure we don't schedule for past. stopIndex = (int) (ticks & mask); - remainingRounds = ticks / wheel.length; + remainingRounds = (calculated - tick) / wheel.length; } @Override diff --git a/common/src/test/java/io/netty/util/HashedWheelTimerTest.java b/common/src/test/java/io/netty/util/HashedWheelTimerTest.java index b9b4160f8d..db1f4625d4 100644 --- a/common/src/test/java/io/netty/util/HashedWheelTimerTest.java +++ b/common/src/test/java/io/netty/util/HashedWheelTimerTest.java @@ -16,8 +16,12 @@ package io.netty.util; import org.junit.Test; + import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -102,4 +106,21 @@ public class HashedWheelTimerTest { } }, 1, TimeUnit.SECONDS); } + + @Test + public void testTimerOverflowWheelLength() throws InterruptedException { + final HashedWheelTimer timer = new HashedWheelTimer( + Executors.defaultThreadFactory(), 100, TimeUnit.MILLISECONDS, 32); + final AtomicInteger counter = new AtomicInteger(); + + timer.newTimeout(new TimerTask() { + @Override + public void run(final Timeout timeout) throws Exception { + counter.incrementAndGet(); + timer.newTimeout(this, 1, TimeUnit.SECONDS); + } + }, 1, TimeUnit.SECONDS); + Thread.sleep(3500); + assertEquals(3, counter.get()); + } }