Skip to content

Respect ctx.read() calls while processing reads for the child channel…#8617

Merged
normanmaurer merged 1 commit into
4.1from
http2_multiplex_read
Dec 5, 2018
Merged

Respect ctx.read() calls while processing reads for the child channel…#8617
normanmaurer merged 1 commit into
4.1from
http2_multiplex_read

Conversation

@normanmaurer
Copy link
Copy Markdown
Member

…s when using the Http2MultiplexCodec.

Motivation:

We did not correct respect ctx.read() calls while processing a read for a child Channel. This could lead to read stales when auto read is disabled and no other read was requested.

Modifications:

  • Keep track of extra read() calls while processing reads
  • Add unit tests that verify that read() is respected when triggered either in channelRead(...) or channelReadComplete(...)

Result:

Fixes #8209.

@normanmaurer
Copy link
Copy Markdown
Member Author

@rschmitt FYI... this should fix your problem. Thanks again for the reproducer.

assert next == null && previous == null;
readInProgress = false;
if (readStatus == ReadStatus.REQUESTED) {
readStatus = ReadStatus.IN_PROGRESS;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure this is all you have to do? If auto-read is disabled on the parent channel, might you not have to request a read to ensure progress? (This may happen somewhere else, but I can't see where.)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rschmitt that is a different "issue" and I am not even sure if we should do anything here at all by default. You could easily add a ChannelOutboundHandler to the ChannelPipeline of the Channel which will trigger channel.parent().read() when a read is received.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also make this a ChannelOption on the "child channel".

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to give some more background why I think we should not handle this by default... I think the user may want to handle the read pattern / back pressure independently in some cases.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is the philosophy behind this class, then I have no idea why my current h2 server works, because it only reads from the parent channel one time (right at the end of initChannel), and autoread is constantly disabled on both parent and child streams.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will investigate once this one is pulled in... Like I said I think these are different "concerns".

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rschmitt now that this one is merged I will check your other concern during this week.

* {@link RecvByteBufAllocator} behavior a read may extend beyond the {@link Http2ChannelUnsafe#beginRead()}
* method scope. The {@link Http2ChannelUnsafe#beginRead()} loop may drain all pending data, and then if the
* parent channel is reading this channel may still accept frames.
* This variable represents if a read is in progress for the current channe or was requested.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

channe => channel

ReferenceCountUtil.release(frame);
} else if (readInProgress) {
} else if (readStatus != ReadStatus.IDLE) {
// If readInProgress there cannot be anything in the queue, otherwise we would have drained it from the
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"If a read is in progress or has been requested, there cannot be anything in the queue" (etc)

…s when using the Http2MultiplexCodec.

Motivation:

We did not correct respect ctx.read() calls while processing a read for a child Channel. This could lead to read stales when auto read is disabled and no other read was requested.

Modifications:

- Keep track of extra read() calls while processing reads
- Add unit tests that verify that read() is respected when triggered either in channelRead(...) or channelReadComplete(...)

Result:

Fixes #8209.
@normanmaurer normanmaurer added this to the 4.1.33.Final milestone Dec 4, 2018
@normanmaurer normanmaurer merged commit 9f9aa1a into 4.1 Dec 5, 2018
@normanmaurer normanmaurer deleted the http2_multiplex_read branch December 5, 2018 14:29
normanmaurer added a commit that referenced this pull request Dec 5, 2018
…s when using the Http2MultiplexCodec. (#8617)

Motivation:

We did not correct respect ctx.read() calls while processing a read for a child Channel. This could lead to read stales when auto read is disabled and no other read was requested.

Modifications:

- Keep track of extra read() calls while processing reads
- Add unit tests that verify that read() is respected when triggered either in channelRead(...) or channelReadComplete(...)

Result:

Fixes #8209.
@carl-mastrangelo
Copy link
Copy Markdown
Member

Code LGTM

void fireChildReadComplete() {
assert eventLoop().inEventLoop();
assert readInProgress;
assert readStatus == ReadStatus.IN_PROGRESS;
Copy link
Copy Markdown
Contributor

@bryce-anderson bryce-anderson Dec 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still accurate? If the user had requested a read while in the IN_PROGRESS state I think we transition to the REQUESTED state. In fact, the unsafe.notifyReadComplete call right after the assert will check if we're in the REQUESTED state and transition back to IN_PROGRESS.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bryce-anderson I think you are right... it should be either IN_PROGRESS or REQUESTED. Let me fix this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bryce-anderson PTAL #8639 and thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants