Fixed a bug where ChannelReadTimeoutException and ChannelWriteTimeoutException can be raised after a channel is closed.

This commit is contained in:
Trustin Lee 2009-02-11 04:59:45 +00:00
parent bb898265b9
commit 4ea1d640c2
3 changed files with 21 additions and 11 deletions

View File

@ -44,8 +44,8 @@ public class ReadTimeoutHandler extends SimpleChannelUpstreamHandler implements
static final ChannelReadTimeoutException EXCEPTION = new ChannelReadTimeoutException(); static final ChannelReadTimeoutException EXCEPTION = new ChannelReadTimeoutException();
final Timer timer; final Timer timer;
final long timeoutNanos; final long timeoutMillis;
private volatile Timeout timeout; volatile Timeout timeout;
private volatile ReadTimeoutTask task; private volatile ReadTimeoutTask task;
volatile long lastReadTime; volatile long lastReadTime;
@ -63,7 +63,7 @@ public class ReadTimeoutHandler extends SimpleChannelUpstreamHandler implements
} }
this.timer = timer; this.timer = timer;
timeoutNanos = unit.toNanos(timeout); timeoutMillis = unit.toMillis(timeout);
} }
public void releaseExternalResources() { public void releaseExternalResources() {
@ -103,14 +103,14 @@ public class ReadTimeoutHandler extends SimpleChannelUpstreamHandler implements
@Override @Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception { throws Exception {
lastReadTime = System.nanoTime(); lastReadTime = System.currentTimeMillis();
ctx.sendUpstream(e); ctx.sendUpstream(e);
} }
private void initialize(ChannelHandlerContext ctx) { private void initialize(ChannelHandlerContext ctx) {
lastReadTime = System.nanoTime(); lastReadTime = System.currentTimeMillis();
task = new ReadTimeoutTask(ctx); task = new ReadTimeoutTask(ctx);
timeout = timer.newTimeout(task, timeoutNanos, TimeUnit.NANOSECONDS); timeout = timer.newTimeout(task, timeoutMillis, TimeUnit.MILLISECONDS);
} }
private void destroy() { private void destroy() {
@ -134,15 +134,21 @@ public class ReadTimeoutHandler extends SimpleChannelUpstreamHandler implements
return; return;
} }
long currentTime = System.nanoTime(); if (!ctx.getChannel().isOpen()) {
long nextDelay = timeoutNanos - (currentTime - lastReadTime); return;
}
long currentTime = System.currentTimeMillis();
long nextDelay = timeoutMillis - (currentTime - lastReadTime);
if (nextDelay <= 0) { if (nextDelay <= 0) {
// Read timed out - set a new timeout and notify the callback. // Read timed out - set a new timeout and notify the callback.
timeout = timer.newTimeout(this, timeoutNanos, TimeUnit.NANOSECONDS); ReadTimeoutHandler.this.timeout =
timer.newTimeout(this, timeoutMillis, TimeUnit.MILLISECONDS);
Channels.fireExceptionCaught(ctx, EXCEPTION); Channels.fireExceptionCaught(ctx, EXCEPTION);
} else { } else {
// Read occurred before the timer - set a new timeout with shorter delay. // Read occurred before the timer - set a new timeout with shorter delay.
timeout = timer.newTimeout(this, nextDelay, TimeUnit.NANOSECONDS); ReadTimeoutHandler.this.timeout =
timer.newTimeout(this, nextDelay, TimeUnit.MILLISECONDS);
} }
} }
} }

View File

@ -108,6 +108,10 @@ public class WriteTimeoutHandler extends SimpleChannelDownstreamHandler implemen
return; return;
} }
if (!ctx.getChannel().isOpen()) {
return;
}
// Mark the future as failure // Mark the future as failure
if (future.setFailure(EXCEPTION)) { if (future.setFailure(EXCEPTION)) {
// If succeeded to mark as failure, notify the pipeline, too. // If succeeded to mark as failure, notify the pipeline, too.

View File

@ -37,7 +37,7 @@ import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.MessageEvent;
/** /**
* A servlet that acts as a proxy for a netty channel * A Servlet that acts as a proxy for a netty channel
* *
* @author The Netty Project (netty-dev@lists.jboss.org) * @author The Netty Project (netty-dev@lists.jboss.org)
* @author Andy Taylor (andy.taylor@jboss.org) * @author Andy Taylor (andy.taylor@jboss.org)