diff --git a/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketCloseForciblyTest.java b/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketCloseForciblyTest.java new file mode 100644 index 0000000000..0418f3687f --- /dev/null +++ b/testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketCloseForciblyTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.testsuite.transport.socket; + +import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.socket.SocketChannel; +import org.junit.Test; + +public class SocketCloseForciblyTest extends AbstractSocketTest { + + @Test + public void testCloseForcibly() throws Throwable { + run(); + } + + public void testCloseForcibly(ServerBootstrap sb, Bootstrap cb) throws Throwable { + sb.handler(new ChannelInboundHandlerAdapter() { + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + SocketChannel childChannel = (SocketChannel) msg; + childChannel.config().setSoLinger(0); + childChannel.unsafe().closeForcibly(); + } + }).childHandler(new ChannelInboundHandlerAdapter()); + + cb.handler(new ChannelInboundHandlerAdapter()); + + Channel sc = sb.bind().sync().channel(); + + cb.connect().channel().closeFuture().syncUninterruptibly(); + sc.close().sync(); + } +} diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollChannel.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollChannel.java index fc89fc3b68..b7498dcb3a 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollChannel.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollChannel.java @@ -114,7 +114,9 @@ abstract class AbstractEpollChannel extends AbstractChannel implements UnixChann // socket which has not even been connected yet. This has been observed to block during unit tests. inputClosedSeenErrorOnRead = true; try { - doDeregister(); + if (isRegistered()) { + doDeregister(); + } } finally { socket.close(); } diff --git a/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollSocketCloseForciblyTest.java b/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollSocketCloseForciblyTest.java new file mode 100644 index 0000000000..d3dd45013d --- /dev/null +++ b/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollSocketCloseForciblyTest.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.channel.epoll; + +import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.testsuite.transport.TestsuitePermutation; +import io.netty.testsuite.transport.socket.SocketCloseForciblyTest; + +import java.util.List; + +public class EpollSocketCloseForciblyTest extends SocketCloseForciblyTest { + @Override + protected List> newFactories() { + return EpollSocketTestPermutation.INSTANCE.socket(); + } +} diff --git a/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/AbstractKQueueChannel.java b/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/AbstractKQueueChannel.java index c546aba77d..cf221798f7 100644 --- a/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/AbstractKQueueChannel.java +++ b/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/AbstractKQueueChannel.java @@ -101,7 +101,9 @@ abstract class AbstractKQueueChannel extends AbstractChannel implements UnixChan // The FD will be closed, which will take of deleting from kqueue. readFilterEnabled = writeFilterEnabled = false; try { - ((KQueueEventLoop) eventLoop()).remove(this); + if (isRegistered()) { + ((KQueueEventLoop) eventLoop()).remove(this); + } } finally { socket.close(); } diff --git a/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueSocketCloseForciblyTest.java b/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueSocketCloseForciblyTest.java new file mode 100644 index 0000000000..b9d2c6c94b --- /dev/null +++ b/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueSocketCloseForciblyTest.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.channel.kqueue; + +import io.netty.bootstrap.Bootstrap; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.testsuite.transport.TestsuitePermutation; +import io.netty.testsuite.transport.socket.SocketCloseForciblyTest; + +import java.util.List; + +public class KQueueSocketCloseForciblyTest extends SocketCloseForciblyTest { + @Override + protected List> newFactories() { + return KQueueSocketTestPermutation.INSTANCE.socket(); + } +}