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:
parent
b65c8716a5
commit
18bda09d6c
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user