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

Fixes #11016 - Jetty 12 IllegalStateException when stopping Server wi… #11017

Merged

Conversation

sbordet
Copy link
Contributor

@sbordet sbordet commented Dec 3, 2023

…th pending requests

  • Made ServletChannel error handling more robust. A failure in error handling is now remembered so that the Handler callback can be failed later.
  • Avoid failing the Handler callback from ServletChannel.abort(), as it is too early: should be failed when processing the TERMINATED state, similarly to when it is succeeded.
  • Removed dead code from HttpConnection.SendCallback.reset(), since response is always non-null.

…th pending requests

* Made ServletChannel error handling more robust.
A failure in error handling is now remembered so that the Handler callback can be failed later.
* Avoid failing the Handler callback from ServletChannel.abort(), as it is too early: should be failed when processing the TERMINATED state, similarly to when it is succeeded.
* Removed dead code from HttpConnection.SendCallback.reset(), since response is always non-null.

Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
@sbordet sbordet requested a review from gregw December 3, 2023 17:47
@sbordet sbordet linked an issue Dec 3, 2023 that may be closed by this pull request
…ed().

This may run the ErrorHandler twice when using ee10.

Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
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.

Mostly just more comments/javadoc needed... but I think there may be a problem with

@@ -292,19 +293,13 @@ public String getStatusString()
}
}

public boolean completeResponse()
public Throwable completeResponse()
Copy link
Contributor

Choose a reason for hiding this comment

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

The boolean return was giving protection against calling this method twice.
So either, there is a possibility that we will call it twice, in which case we still need the protection....
OR we will never call it twice, so instead we should throw ISE if we are ever called with it is already in COMPLETED state.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This method is only called once because it is protected by the ServletChannel state machine.
From ServletChannel.handle(), we end up in the TERMINATED state where we call onCompleted() that calls this method.

Copy link
Contributor

Choose a reason for hiding this comment

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

So can we have an assert (or ISE) if it is already in COMPLETED state

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure what you refer to, as there are many COMPLETED states?
If you refer to _outputState it can also be ABORTED.
I feel like we don't need this extra assert, as we just want to make the transition OPEN -> COMPLETED.

Copy link
Contributor

Choose a reason for hiding this comment

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

This method used to return a boolean that indicated if it had just transitioned from OPEN->COMPLETED. If it returned false, then the callback would not be completed.

Now it returns a throwable to say if there has been a failure, in which case the callback is failed. But it has lost the protection for multiple calls, so the callback might be called twice.

I understand that you know this cannot happen because of external factors.... that nothing in this method represents that invariant. It would be clearer if it had something like:

    assert _failure != null || _outputState == OutputState.OPEN

If this assert does not hold, then this PR has changed behaviour in a non obvious way.

@joakime joakime linked an issue Dec 13, 2023 that may be closed by this pull request
Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
@sbordet sbordet requested a review from gregw December 14, 2023 09:13
gregw
gregw previously approved these changes Dec 15, 2023
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.

All good, but a couple of nigglets.

@@ -292,19 +293,13 @@ public String getStatusString()
}
}

public boolean completeResponse()
public Throwable completeResponse()
Copy link
Contributor

Choose a reason for hiding this comment

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

So can we have an assert (or ISE) if it is already in COMPLETED state

@@ -735,10 +729,13 @@ public void onCompleted()
_servletContextRequest.setAttribute(CustomRequestLog.LOG_DETAIL, logDetail);
}

// Callback will either be succeeded here or failed in abort().
// Callback is completed here.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we say:

Suggested change
// Callback is completed here.
// Callback is only completed here.

…pended-request-ise'.

Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
gregw
gregw previously approved these changes Dec 15, 2023
@@ -292,19 +293,13 @@ public String getStatusString()
}
}

public boolean completeResponse()
public Throwable completeResponse()
Copy link
Contributor

Choose a reason for hiding this comment

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

This method used to return a boolean that indicated if it had just transitioned from OPEN->COMPLETED. If it returned false, then the callback would not be completed.

Now it returns a throwable to say if there has been a failure, in which case the callback is failed. But it has lost the protection for multiple calls, so the callback might be called twice.

I understand that you know this cannot happen because of external factors.... that nothing in this method represents that invariant. It would be clearer if it had something like:

    assert _failure != null || _outputState == OutputState.OPEN

If this assert does not hold, then this PR has changed behaviour in a non obvious way.

Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
@sbordet sbordet merged commit eb1e9eb into jetty-12.0.x Dec 15, 2023
2 of 4 checks passed
@sbordet sbordet deleted the fix/jetty-12/11016/server-stop-suspended-request-ise branch December 15, 2023 14:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Status: ✅ Done
2 participants