Resolved issue: NETTY-256 (A race condition during the recommended server shutdown procedure)
* Fixed a bug in the socket transport implementations where a new connection can be accepted after the ChannelFuture of ServerSocketChannel.close() is complete. * Introduced a lock to ensure that the boss thread is terminated before notifying the future
This commit is contained in:
parent
1688569758
commit
42d2f79239
@ -20,6 +20,8 @@ import static org.jboss.netty.channel.Channels.*;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.jboss.netty.channel.AbstractServerChannel;
|
||||
import org.jboss.netty.channel.ChannelException;
|
||||
@ -46,6 +48,7 @@ class NioServerSocketChannel extends AbstractServerChannel
|
||||
InternalLoggerFactory.getInstance(NioServerSocketChannel.class);
|
||||
|
||||
final ServerSocketChannel socket;
|
||||
final Lock shutdownLock = new ReentrantLock();
|
||||
private final ServerSocketChannelConfig config;
|
||||
|
||||
NioServerSocketChannel(
|
||||
|
@ -175,6 +175,12 @@ class NioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
boolean bound = channel.isBound();
|
||||
try {
|
||||
channel.socket.close();
|
||||
|
||||
// Make sure the boss thread is not running so that that the future
|
||||
// is notified after a new connection cannot be accepted anymore.
|
||||
// See NETTY-256 for more information.
|
||||
channel.shutdownLock.lock();
|
||||
try {
|
||||
if (channel.setClosed()) {
|
||||
future.setSuccess();
|
||||
if (bound) {
|
||||
@ -184,6 +190,9 @@ class NioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
} else {
|
||||
future.setSuccess();
|
||||
}
|
||||
} finally {
|
||||
channel.shutdownLock.unlock();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
fireExceptionCaught(channel, t);
|
||||
@ -218,6 +227,7 @@ class NioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
public void run() {
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
|
||||
channel.shutdownLock.lock();
|
||||
for (;;) {
|
||||
try {
|
||||
if (selector.select(1000) > 0) {
|
||||
@ -249,6 +259,7 @@ class NioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
}
|
||||
}
|
||||
|
||||
channel.shutdownLock.unlock();
|
||||
closeSelector();
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,8 @@ import static org.jboss.netty.channel.Channels.*;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.jboss.netty.channel.AbstractServerChannel;
|
||||
import org.jboss.netty.channel.ChannelException;
|
||||
@ -47,6 +49,7 @@ class OioServerSocketChannel extends AbstractServerChannel
|
||||
InternalLoggerFactory.getInstance(OioServerSocketChannel.class);
|
||||
|
||||
final ServerSocket socket;
|
||||
final Lock shutdownLock = new ReentrantLock();
|
||||
private final ServerSocketChannelConfig config;
|
||||
|
||||
OioServerSocketChannel(
|
||||
|
@ -164,6 +164,12 @@ class OioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
boolean bound = channel.isBound();
|
||||
try {
|
||||
channel.socket.close();
|
||||
|
||||
// Make sure the boss thread is not running so that that the future
|
||||
// is notified after a new connection cannot be accepted anymore.
|
||||
// See NETTY-256 for more information.
|
||||
channel.shutdownLock.lock();
|
||||
try {
|
||||
if (channel.setClosed()) {
|
||||
future.setSuccess();
|
||||
if (bound) {
|
||||
@ -173,6 +179,9 @@ class OioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
} else {
|
||||
future.setSuccess();
|
||||
}
|
||||
} finally {
|
||||
channel.shutdownLock.unlock();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
future.setFailure(t);
|
||||
fireExceptionCaught(channel, t);
|
||||
@ -187,6 +196,7 @@ class OioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
}
|
||||
|
||||
public void run() {
|
||||
channel.shutdownLock.lock();
|
||||
while (channel.isBound()) {
|
||||
try {
|
||||
Socket acceptedSocket = channel.socket.accept();
|
||||
@ -238,6 +248,7 @@ class OioServerSocketPipelineSink extends AbstractChannelSink {
|
||||
}
|
||||
}
|
||||
}
|
||||
channel.shutdownLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user