NOTE
4. Register Read Events with the Selector
1. Code to analyze 2. Set a breakpoint and connect with nc 3. Propagate channelActive 4. Reach HeadContext 5. Read through AbstractUnsafe
This is a historical learning note and may contain outdated or incomplete understanding.
1. Code to Analyze
- The registration operation in
io.netty.channel.AbstractChannel.AbstractUnsafe#register.
//...
register0(promise);//...
//...
2. Set a Breakpoint and Connect with nc
This is actually similar to registering accept with the selector when the server starts. Look at io.netty.channel.AbstractChannel.AbstractUnsafe#register0.
Connect using nc, and execution eventually reaches pipeline.fireChannelActive().
private void register0(ChannelPromise promise) {
try {
//.....
// Set a breakpoint on this line.
if (isActive()) {
if (firstRegistration) {
// Call pipeline.fireChannelActive.
pipeline.fireChannelActive();
} else if (config().isAutoRead()) {
// This channel was registered before and autoRead() is set. This means we need to begin read
// again so that we process inbound data.
//
// See https://github.com/netty/netty/issues/4805
beginRead();
}
}
} catch (Throwable t) {
// Close the channel directly to avoid FD leak.
closeForcibly();
closeFuture.setClosed();
safeSetFailure(promise, t);
}
}
3. Propagate the channelActive Event Through the Pipeline
DefaultChannelPipeline#fireChannelActive
public final ChannelPipeline fireChannelActive() {
// io.netty.channel.AbstractChannelHandlerContext#invokeChannelActive(io.netty.channel.AbstractChannelHandlerContext)
// Propagate through AbstractChannelHandlerContext.
AbstractChannelHandlerContext.invokeChannelActive(head);
return this;
}
3.1. Propagate Through AbstractChannelHandlerContext
AbstractChannelHandlerContext#invokeChannelActive
static void invokeChannelActive(final AbstractChannelHandlerContext next) {
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
// Enters here.
// io.netty.channel.AbstractChannelHandlerContext#invokeChannelActive()
next.invokeChannelActive();
} else {
executor.execute(new Runnable() {
@Override
public void run() {
next.invokeChannelActive();
}
});
}
}
AbstractChannelHandlerContext#invokeChannelActive()
private void invokeChannelActive() {
if (invokeHandler()) {
try {
// io.netty.channel.DefaultChannelPipeline.HeadContext#channelActive
((ChannelInboundHandler) handler()).channelActive(this);
} catch (Throwable t) {
notifyHandlerException(t);
}
} else {
fireChannelActive();
}
}
4. Reach HeadContext First
DefaultChannelPipeline.HeadContext#channelActive
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.fireChannelActive();
// io.netty.channel.DefaultChannelPipeline.HeadContext#readIfIsAutoRead
readIfIsAutoRead();
}
4.1. Call Channel.read
DefaultChannelPipeline.HeadContext#readIfIsAutoRead
private void readIfIsAutoRead() {
if (channel.config().isAutoRead()) {
// io.netty.channel.AbstractChannel#read
channel.read();
}
}
AbstractChannel#read
public Channel read() {
// Propagate from pipeline tail to head, eventually reaching
// io.netty.channel.AbstractChannel.AbstractUnsafe#beginRead.
pipeline.read();
return this;
}
5. AbstractUnsafe Performs the Read Operation
AbstractChannel.AbstractUnsafe#beginRead
public final void beginRead() {
assertEventLoop();
if (!isActive()) {
return;
}
try {
// io.netty.channel.nio.AbstractNioChannel#doBeginRead
doBeginRead();
} catch (final Exception e) {
invokeLater(new Runnable() {
@Override
public void run() {
pipeline.fireExceptionCaught(e);
}
});
close(voidPromise());
}
}
5.1. Register the Read Event
AbstractNioChannel#doBeginRead
protected void doBeginRead() throws Exception {
// Channel.read() or ChannelHandlerContext.read() was called
final SelectionKey selectionKey = this.selectionKey;
if (!selectionKey.isValid()) {
return;
}
readPending = true;
// Register the read event.
final int interestOps = selectionKey.interestOps();
if ((interestOps & readInterestOp) == 0) {
selectionKey.interestOps(interestOps | readInterestOp);
}
}
Discussion
Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub