Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #5605 - Async Request Timeout results in Blocked Thread #5923

Conversation

lorban
Copy link
Contributor

@lorban lorban commented Jan 27, 2021

Fixes #5605

Signed-off-by: Ludovic Orban <lorban@bitronix.be>
Signed-off-by: Ludovic Orban <lorban@bitronix.be>
Signed-off-by: Ludovic Orban <lorban@bitronix.be>
@lorban lorban requested a review from gregw January 27, 2021 10:33
Copy link
Contributor

@gregw gregw left a comment

Choose a reason for hiding this comment

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

So in general I think the approach is OK:

  • we are failing HttpInput on sendError and termination so any random thread that tries to read after that point will have a problem. We are also cancelling any associated fillInterest at the same time.
  • we have replaced calls to plain fillInterest with versions that can cope with being register-bombed by some random thread - by either turning into a noop or cancelling the bomber.

My concern is that it may not be universal, but then it wasn't before. So if we can at least make it low cost and understandable, we are improving code.

@@ -366,6 +366,8 @@ public boolean handle()
{
case TERMINATED:
onCompleted();
_request.getHttpInput().failed(new IOException("terminated"));
Copy link
Contributor

Choose a reason for hiding this comment

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

Ideally this exception should only be created if it is needed.

@@ -366,6 +366,8 @@ public boolean handle()
{
case TERMINATED:
onCompleted();
_request.getHttpInput().failed(new IOException("terminated"));
getEndPoint().cancelFillInterested();
Copy link
Contributor

Choose a reason for hiding this comment

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

If we do create an exception for the step above, it should be passed into this cancel so we don't create another one. Or maybe the HttpInput does this cancel for us?

Comment on lines +410 to +411
_request.getHttpInput().failed(new IOException("cancellation"));
getEndPoint().cancelFillInterested();
Copy link
Contributor

Choose a reason for hiding this comment

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

If there is an exception associated with the sendError, it should be used for the fail and the cancel.
If a new exception is needed, it should be the same exception for the failed and the cancel
perhaps httpInput.failed can do the the cancel

@@ -278,7 +278,7 @@ else if (filled == -1 && getEndPoint().isOutputShutdown())
}
else if (filled == 0)
{
fillInterested();
tryFillInterested();
Copy link
Contributor

Choose a reason for hiding this comment

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

We need to review all other calls to fillInterested as any of them can be register-bombed by some random thread doing a read

Signed-off-by: Ludovic Orban <lorban@bitronix.be>
@joakime
Copy link
Contributor

joakime commented Jan 27, 2021

Don't forget to to do the metadata on this PR: link the issue, add labels, add to a project, etc ...

@lorban lorban linked an issue Jan 27, 2021 that may be closed by this pull request
@lorban lorban self-assigned this Jan 27, 2021
@lorban lorban added the Bug For general bugs on Jetty side label Jan 27, 2021
@lorban lorban added this to the 9.4.x milestone Jan 27, 2021
@lorban lorban added this to In progress in Jetty 10.0.1 via automation Jan 27, 2021
@lorban lorban added this to In progress in Jetty 11.0.1 via automation Jan 27, 2021
@lorban lorban added this to In progress in Jetty 9.4.37 via automation Jan 27, 2021
@joakime joakime changed the title Jetty 9.4.x 5605 async request timeout blocked thread Issue #5605 - Async Request Timeout results in Blocked Thread Jan 27, 2021
Signed-off-by: Ludovic Orban <lorban@bitronix.be>
getEndPoint().cancelFillInterested();
if (_request.getHttpInput().isError())
{
_request.getHttpInput().failed(new IOException("terminated"));
Copy link
Contributor

Choose a reason for hiding this comment

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

If we are already in error, then why do we need to fail again? Any caller will not block in read and get an exception either way.

Copy link
Contributor Author

@lorban lorban Jan 27, 2021

Choose a reason for hiding this comment

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

If we blindly fail the input upon termination, any content already parsed but not yet consumed by the servlet will be discarded and make the servlet throw an exception while there was no error. If we do not fail again, then there's still the risk of a thread still being stuck in a blocking read after the async timeout.

This extra hack seems to fix a good chunk of the tests that failed during the previous build, it just adds to the cleanup that will be needed to get this PR to a reasonable state.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't doubt we need to be smart here and not break chained requests. I was thinking more that if we are at EOF then we do nothing.
What I don't understand is how replacing and error with another error is helping? Is it just the cancel on the next line?
I think we need to understand why this works.

@lorban lorban closed this Feb 11, 2021
Jetty 10.0.1 automation moved this from In progress to Done Feb 11, 2021
Jetty 11.0.1 automation moved this from In progress to Done Feb 11, 2021
Jetty 9.4.37 automation moved this from In progress to Done Feb 11, 2021
@joakime joakime deleted the jetty-9.4.x-5605-async-request-timeout-blocked-thread branch February 18, 2021 13:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug For general bugs on Jetty side
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

Blocked IO Thread not woken
3 participants