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.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.channels.ServerSocketChannel;
|
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.AbstractServerChannel;
|
||||||
import org.jboss.netty.channel.ChannelException;
|
import org.jboss.netty.channel.ChannelException;
|
||||||
@ -46,6 +48,7 @@ class NioServerSocketChannel extends AbstractServerChannel
|
|||||||
InternalLoggerFactory.getInstance(NioServerSocketChannel.class);
|
InternalLoggerFactory.getInstance(NioServerSocketChannel.class);
|
||||||
|
|
||||||
final ServerSocketChannel socket;
|
final ServerSocketChannel socket;
|
||||||
|
final Lock shutdownLock = new ReentrantLock();
|
||||||
private final ServerSocketChannelConfig config;
|
private final ServerSocketChannelConfig config;
|
||||||
|
|
||||||
NioServerSocketChannel(
|
NioServerSocketChannel(
|
||||||
|
@ -175,6 +175,12 @@ class NioServerSocketPipelineSink extends AbstractChannelSink {
|
|||||||
boolean bound = channel.isBound();
|
boolean bound = channel.isBound();
|
||||||
try {
|
try {
|
||||||
channel.socket.close();
|
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()) {
|
if (channel.setClosed()) {
|
||||||
future.setSuccess();
|
future.setSuccess();
|
||||||
if (bound) {
|
if (bound) {
|
||||||
@ -184,6 +190,9 @@ class NioServerSocketPipelineSink extends AbstractChannelSink {
|
|||||||
} else {
|
} else {
|
||||||
future.setSuccess();
|
future.setSuccess();
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
channel.shutdownLock.unlock();
|
||||||
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
future.setFailure(t);
|
future.setFailure(t);
|
||||||
fireExceptionCaught(channel, t);
|
fireExceptionCaught(channel, t);
|
||||||
@ -218,6 +227,7 @@ class NioServerSocketPipelineSink extends AbstractChannelSink {
|
|||||||
public void run() {
|
public void run() {
|
||||||
final Thread currentThread = Thread.currentThread();
|
final Thread currentThread = Thread.currentThread();
|
||||||
|
|
||||||
|
channel.shutdownLock.lock();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
try {
|
try {
|
||||||
if (selector.select(1000) > 0) {
|
if (selector.select(1000) > 0) {
|
||||||
@ -249,6 +259,7 @@ class NioServerSocketPipelineSink extends AbstractChannelSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channel.shutdownLock.unlock();
|
||||||
closeSelector();
|
closeSelector();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@ import static org.jboss.netty.channel.Channels.*;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.ServerSocket;
|
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.AbstractServerChannel;
|
||||||
import org.jboss.netty.channel.ChannelException;
|
import org.jboss.netty.channel.ChannelException;
|
||||||
@ -47,6 +49,7 @@ class OioServerSocketChannel extends AbstractServerChannel
|
|||||||
InternalLoggerFactory.getInstance(OioServerSocketChannel.class);
|
InternalLoggerFactory.getInstance(OioServerSocketChannel.class);
|
||||||
|
|
||||||
final ServerSocket socket;
|
final ServerSocket socket;
|
||||||
|
final Lock shutdownLock = new ReentrantLock();
|
||||||
private final ServerSocketChannelConfig config;
|
private final ServerSocketChannelConfig config;
|
||||||
|
|
||||||
OioServerSocketChannel(
|
OioServerSocketChannel(
|
||||||
|
@ -164,6 +164,12 @@ class OioServerSocketPipelineSink extends AbstractChannelSink {
|
|||||||
boolean bound = channel.isBound();
|
boolean bound = channel.isBound();
|
||||||
try {
|
try {
|
||||||
channel.socket.close();
|
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()) {
|
if (channel.setClosed()) {
|
||||||
future.setSuccess();
|
future.setSuccess();
|
||||||
if (bound) {
|
if (bound) {
|
||||||
@ -173,6 +179,9 @@ class OioServerSocketPipelineSink extends AbstractChannelSink {
|
|||||||
} else {
|
} else {
|
||||||
future.setSuccess();
|
future.setSuccess();
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
channel.shutdownLock.unlock();
|
||||||
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
future.setFailure(t);
|
future.setFailure(t);
|
||||||
fireExceptionCaught(channel, t);
|
fireExceptionCaught(channel, t);
|
||||||
@ -187,6 +196,7 @@ class OioServerSocketPipelineSink extends AbstractChannelSink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
|
channel.shutdownLock.lock();
|
||||||
while (channel.isBound()) {
|
while (channel.isBound()) {
|
||||||
try {
|
try {
|
||||||
Socket acceptedSocket = channel.socket.accept();
|
Socket acceptedSocket = channel.socket.accept();
|
||||||
@ -238,6 +248,7 @@ class OioServerSocketPipelineSink extends AbstractChannelSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
channel.shutdownLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user