Correct throw ClosedChannelException when attempt to call shutdown*(...) on closed EpollSocketChannel.

Motivition:

NIO throws ClosedChannelException when a user tries to call shutdown*() on a closed Channel. We should do the same for the EPOLL transport

Modification:

Throw ClosedChannelException when a user tries to call shutdown*() on a closed channel.

Result:

Consistent behavior.
This commit is contained in:
Norman Maurer 2016-08-29 08:00:34 +02:00
parent 3051df8961
commit eb450d8b2f
2 changed files with 47 additions and 0 deletions

View File

@ -25,6 +25,8 @@ import org.junit.Test;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import java.net.SocketException;
import java.nio.channels.ClosedChannelException;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
@ -76,6 +78,48 @@ public class SocketShutdownOutputBySelfTest extends AbstractClientSocketTest {
} }
} }
@Test(timeout = 30000)
public void testShutdownOutputAfterClosed() throws Throwable {
run();
}
public void testShutdownOutputAfterClosed(Bootstrap cb) throws Throwable {
TestHandler h = new TestHandler();
ServerSocket ss = new ServerSocket();
Socket s = null;
try {
ss.bind(addr);
SocketChannel ch = (SocketChannel) cb.handler(h).connect().sync().channel();
assertTrue(ch.isActive());
s = ss.accept();
ch.close().syncUninterruptibly();
try {
ch.shutdownInput().syncUninterruptibly();
fail();
} catch (Throwable cause) {
checkThrowable(cause);
}
try {
ch.shutdownOutput().syncUninterruptibly();
fail();
} catch (Throwable cause) {
checkThrowable(cause);
}
} finally {
if (s != null) {
s.close();
}
ss.close();
}
}
private static void checkThrowable(Throwable cause) throws Throwable {
// Depending on OIO / NIO both are ok
if (!(cause instanceof ClosedChannelException) && !(cause instanceof SocketException)) {
throw cause;
}
}
private static class TestHandler extends SimpleChannelInboundHandler<ByteBuf> { private static class TestHandler extends SimpleChannelInboundHandler<ByteBuf> {
volatile SocketChannel ch; volatile SocketChannel ch;
final BlockingQueue<Byte> queue = new LinkedBlockingQueue<Byte>(); final BlockingQueue<Byte> queue = new LinkedBlockingQueue<Byte>();

View File

@ -82,6 +82,9 @@ public final class Socket extends FileDescriptor {
// represents the previous incarnation of the FD we need to be sure we don't inadvertently shutdown the // represents the previous incarnation of the FD we need to be sure we don't inadvertently shutdown the
// "new" FD without explicitly having a change. // "new" FD without explicitly having a change.
final int oldState = this.state; final int oldState = this.state;
if (isClosed(oldState)) {
throw new ClosedChannelException();
}
int newState = oldState; int newState = oldState;
if (read && !isInputShutdown(newState)) { if (read && !isInputShutdown(newState)) {
newState = inputShutdown(newState); newState = inputShutdown(newState);