Allow to recover from exception triggered by accept() more easily

This is done by stop accept() new sockets for 1 seconds
Beside this this commit also makes sure accept() exceptions of OioServerSocketChannel trigger
the fireExceptionCaught(...). The same is true fo the AioServerSocketChannel.
This commit is contained in:
Norman Maurer 2013-05-08 06:57:52 +02:00
parent b65c8716a5
commit 18bda09d6c
3 changed files with 37 additions and 15 deletions

View File

@ -18,6 +18,7 @@ package io.netty.bootstrap;
import io.netty.buffer.MessageBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelConfig;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandler;
@ -35,6 +36,7 @@ import io.netty.util.internal.logging.InternalLoggerFactory;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
/**
* {@link Bootstrap} sub-class which allows easy bootstrap of {@link ServerChannel}
@ -267,6 +269,25 @@ public final class ServerBootstrap extends AbstractBootstrap<ServerBootstrap, Se
}
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
final ChannelConfig config = ctx.channel().config();
if (config.isAutoRead()) {
// stop accept new connections for 1 second to allow the channel to recover
// See https://github.com/netty/netty/issues/1328
config.setAutoRead(false);
ctx.channel().eventLoop().schedule(new Runnable() {
@Override
public void run() {
config.setAutoRead(true);
}
}, 1, TimeUnit.SECONDS);
}
// still let the exceptionCaught event flow through the pipeline to give the user
// a chance to do something with it
ctx.fireExceptionCaught(cause);
}
}
@Override

View File

@ -216,6 +216,7 @@ public class AioServerSocketChannel extends AbstractAioChannel implements Server
// log something
if (channel.isOpen() && ! asyncClosed) {
logger.warn("Failed to create a new channel from an accepted socket.", t);
channel.pipeline().fireExceptionCaught(t);
}
}
}

View File

@ -160,26 +160,26 @@ public class OioServerSocketChannel extends AbstractOioMessageChannel
return -1;
}
Socket s = null;
try {
s = socket.accept();
if (s != null) {
buf.add(new OioSocketChannel(this, null, s));
return 1;
Socket s = socket.accept();
try {
if (s != null) {
buf.add(new OioSocketChannel(this, null, s));
return 1;
}
} catch (Throwable t) {
logger.warn("Failed to create a new channel from an accepted socket.", t);
if (s != null) {
try {
s.close();
} catch (Throwable t2) {
logger.warn("Failed to close a socket.", t2);
}
}
}
} catch (SocketTimeoutException e) {
// Expected
} catch (Throwable t) {
logger.warn("Failed to create a new channel from an accepted socket.", t);
if (s != null) {
try {
s.close();
} catch (Throwable t2) {
logger.warn("Failed to close a socket.", t2);
}
}
}
return 0;
}