HashedWheelTimer.newTimeout(...) may overflow

Motivation:

We dont protect from overflow and so the timer may fire too early if a large timeout is used.

Modifications:

Add overflow guard and a test.

Result:

Fixes https://github.com/netty/netty/issues/7760.
This commit is contained in:
Norman Maurer 2018-03-02 17:59:43 +09:00 committed by Norman Maurer
parent 0a8e1aaf19
commit 48df2f66b8
2 changed files with 20 additions and 0 deletions

View File

@ -419,6 +419,11 @@ public class HashedWheelTimer implements Timer {
// Add the timeout to the timeout queue which will be processed on the next tick. // Add the timeout to the timeout queue which will be processed on the next tick.
// During processing all the queued HashedWheelTimeouts will be added to the correct HashedWheelBucket. // During processing all the queued HashedWheelTimeouts will be added to the correct HashedWheelBucket.
long deadline = System.nanoTime() + unit.toNanos(delay) - startTime; long deadline = System.nanoTime() + unit.toNanos(delay) - startTime;
// Guard against overflow.
if (delay > 0 && deadline < 0) {
deadline = Long.MAX_VALUE;
}
HashedWheelTimeout timeout = new HashedWheelTimeout(this, task, deadline); HashedWheelTimeout timeout = new HashedWheelTimeout(this, task, deadline);
timeouts.add(timeout); timeouts.add(timeout);
return timeout; return timeout;

View File

@ -230,6 +230,21 @@ public class HashedWheelTimerTest {
timer.stop(); timer.stop();
} }
@Test
public void testOverflow() throws InterruptedException {
final HashedWheelTimer timer = new HashedWheelTimer();
final CountDownLatch latch = new CountDownLatch(1);
Timeout timeout = timer.newTimeout(new TimerTask() {
@Override
public void run(Timeout timeout) {
latch.countDown();
}
}, Long.MAX_VALUE, TimeUnit.MILLISECONDS);
assertFalse(latch.await(1, TimeUnit.SECONDS));
timeout.cancel();
timer.stop();
}
private static TimerTask createNoOpTimerTask() { private static TimerTask createNoOpTimerTask() {
return new TimerTask() { return new TimerTask() {
@Override @Override