[#1385] Fix NPE which was triggered if a write was executed but the HeadHandler not init yet

This commit is contained in:
Norman Maurer 2013-05-23 07:42:01 +02:00
parent 1801ecfe30
commit 9c925b104a
2 changed files with 78 additions and 2 deletions

View File

@ -0,0 +1,57 @@
/*
* Copyright 2013 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.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelStateHandlerAdapter;
import io.netty.channel.socket.SocketChannel;
import org.junit.Test;
public class WriteBeforeRegisteredTest extends AbstractClientSocketTest {
@Test(timeout = 30000)
public void testWriteBeforeConnect() throws Throwable {
run();
}
public void testWriteBeforeConnect(Bootstrap cb) throws Throwable {
TestHandler h = new TestHandler();
SocketChannel ch = null;
try {
ch = (SocketChannel) cb.handler(h).connect().channel();
ch.write(Unpooled.wrappedBuffer(new byte[] { 1 })).await();
} finally {
if (ch != null) {
ch.close();
}
}
}
private static class TestHandler extends ChannelStateHandlerAdapter {
@Override
public void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {
ctx.fireInboundBufferUpdated();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
}
}
}

View File

@ -1502,7 +1502,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
validateFuture(promise, true);
DefaultChannelHandlerContext ctx = prev;
EventExecutor executor;
EventExecutor executor = executor();
final boolean msgBuf;
if (message instanceof ByteBuf) {
@ -1519,7 +1519,26 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
break;
}
ctx = ctx.prev;
DefaultChannelHandlerContext prev = ctx.prev;
if (prev == null) {
assert ctx == pipeline.head;
// this means we reached end of pipeline but the head-handler was not yet init.
// in this case init it now and schedule the write via the executor so it is
// done after fireChannelRegistered() completes
//
// See https://github.com/netty/netty/issues/1385
ctx.initHeadHandler();
executor.execute(new Runnable() {
@Override
public void run() {
write(message, promise);
}
});
return promise;
} else {
ctx = prev;
}
}
} else {
msgBuf = true;