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

7026262: HttpServer: improve handling of finished HTTP exchanges #13157

Closed
wants to merge 7 commits into from

Conversation

djelinski
Copy link
Member

@djelinski djelinski commented Mar 23, 2023

This patch fixes the following issues with HttpHandler exception handling:

  • The connection is no longer closed if an exception is thrown after the response is completed. As soon as the response is completed, the connection is added back to the pool, ready for reuse. Closing the connection would race with the subsequent handler.
  • The stream returned by getResponseBody is now usable even if the response has zero-length body. Writing any data to the stream will still fail, but zero-length writes and closing the stream will now succeed.
  • ServerImpl.Exchange.reject now sends a Connection: close header in addition to closing the connection

The test B8293562 had to be adjusted to avoid Connection: close.
Additionally, while I was looking for a good test to copy from, I found and fixed a bug in test B5045306.

The new tests are passing with this patch, failing without it. Tier 1-3 clean.


Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue

Issue

  • JDK-7026262: HttpServer: improve handling of finished HTTP exchanges

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/13157/head:pull/13157
$ git checkout pull/13157

Update a local copy of the PR:
$ git checkout pull/13157
$ git pull https://git.openjdk.org/jdk.git pull/13157/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 13157

View PR using the GUI difftool:
$ git pr show -t 13157

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/13157.diff

@bridgekeeper
Copy link

bridgekeeper bot commented Mar 23, 2023

👋 Welcome back djelinski! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk openjdk bot changed the title 7026262 7026262: HttpServer: improve handling of finished HTTP exchanges Mar 23, 2023
@openjdk
Copy link

openjdk bot commented Mar 23, 2023

@djelinski The following label will be automatically applied to this pull request:

  • net

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added the net net-dev@openjdk.org label Mar 23, 2023
@djelinski djelinski marked this pull request as ready for review March 23, 2023 15:50
@openjdk openjdk bot added the rfr Pull request is ready for review label Mar 23, 2023
@mlbridge
Copy link

mlbridge bot commented Mar 23, 2023

Webrevs

Comment on lines 86 to 89
if (zerolength) {
// WriteFinishedEvent was sent already; nothing to do
return;
}
Copy link
Member

Choose a reason for hiding this comment

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

Wouldn't it be more correct to have sendResponseHeader close the output stream, and let the output stream close generate the write event, rather than having sendResponseHeader generate the event and not doing anything here? Or would there be an issue with the case where the stream is chunked output stream?

Copy link
Member Author

Choose a reason for hiding this comment

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

sendResponseStream could close the stream when called with length = -1; the output stream is always fixed length in that case. I'd need to modify this class to accept zero-length writes even when closed, but I think there's a precedent for that already. Will look into it.

Copy link
Member

Choose a reason for hiding this comment

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

That was just a suggestion - I was a bit bothered with the hidden interaction between FixedLengthOutputStream and sendResponseHeaders here, where FixedLengthOutputStream has to trust that sendResponseHeaders has sent the event. It looked strange. Maybe there are other possibilities - like e.g a ZeroLengthOutputStream :-)

Copy link
Member Author

Choose a reason for hiding this comment

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

I changed sendResponseHeaders to close the exchange, and I like the result much better.
ExceptionKeepAlive test no longer needs to explicitly close the request body before sending the response - exchange's close takes care of that.
Let me know what you think.

Copy link
Member

@Michael-Mc-Mahon Michael-Mc-Mahon Mar 24, 2023

Choose a reason for hiding this comment

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

I wonder should we move the code that sends the write finished event in this case to here? I agree this code looks pretty strange. Never mind. I see this has changed in the new revision.

Comment on lines -73 to -76
eof = (remaining == 0);
if (eof) {
throw new StreamClosedException();
}
Copy link
Member

Choose a reason for hiding this comment

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

Maybe before checking closed we should just return if len == 0? (and throw if < 0 BTW)
Possibly consider doing the same for ChunkedOutputStream.
Also ChunkedOutputStream throws StreamClosedException() when closed is true. Not sure why we're throwing plain IO here. Or rather - not sure why we have StreamClosedException() in the first place, it doesn't seem to be handled specially anywhere, and it can reach user code (code calling write()), and it's not a public exception - so maybe it should be removed altogether and replaced with IOException("stream closed") everywhere? But getting rid of StreamClosedException may be a task for another PR.

Copy link
Member Author

Choose a reason for hiding this comment

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

+1. Filed JDK-8304873 to remove StreamClosedException.

Copy link
Member

@dfuch dfuch left a comment

Choose a reason for hiding this comment

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

That looks much cleaner. It would be good to get @Michael-Mc-Mahon review too. But if all tests are passing and stable, it sounds good to me.

@openjdk
Copy link

openjdk bot commented Mar 24, 2023

@djelinski This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

7026262: HttpServer: improve handling of finished HTTP exchanges

Reviewed-by: dfuchs, michaelm

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 33 new commits pushed to the master branch:

  • d8ba227: 8304069: ClassFileParser has ad-hoc hashtables
  • 9a8a60f: 8304833: (fc) Remove dead code in sun.nio.ch.FileChannelImpl::implCloseChannel
  • f96aee7: 8291154: Create a non static nested class without enclosing class throws VerifyError
  • 4ec720d: 8297977: vmTestbase/nsk/stress/except/except012.java fails with unexpected Exception
  • 13dd19a: 8304802: After JDK-8297639 the flag G1UsePreventiveGC needs to be added to the obsoletion table
  • d61de14: 8303508: Vector.lane() gets wrong value on x86
  • 941a7ac: 8304301: Remove the global option SuperWordMaxVectorSize
  • ac6af6a: 7176515: ExceptionInInitializerError for an enum with multiple switch statements
  • dd23ee9: 8303917: Update ISO 639 language codes table
  • 6f67abd: 8304557: java/util/concurrent/CompletableFuture/CompletableFutureOrTimeoutExceptionallyTest.java times out
  • ... and 23 more: https://git.openjdk.org/jdk/compare/ddf1e34c1a0815e8677212f1a7860ca7cf9fc2c9...master

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the master branch, type /integrate in a new comment.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Mar 24, 2023
Copy link
Member

@Michael-Mc-Mahon Michael-Mc-Mahon left a comment

Choose a reason for hiding this comment

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

Looks fine to me

Objects.checkFromIndexSize(off, len, b.length);
if (len == 0) {
return;
}
if (closed) {
Copy link
Member

Choose a reason for hiding this comment

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

Initially I didnt think the above was a great idea as OutputStream.write is spec'd to throw IOE if the stream is closed, but it appears that some commonly used OutputStream classes are tolerant of zero length writes

@djelinski
Copy link
Member Author

/integrate

@openjdk
Copy link

openjdk bot commented Mar 27, 2023

Going to push as commit a5ffa07.
Since your change was applied there have been 40 commits pushed to the master branch:

  • 65e01da: 8304013: Add a fast, non-manual alternative to test/jdk/java/util/zip/ZipFile/TestTooManyEntries
  • 38e1714: 8304258: x86: Improve the code generation of VectorRearrange with int and float
  • 765a942: 8304136: Match allocation and free in sspi.cpp
  • 3f59b75: 8304898: Fix Copyright Headers for JLink Source Files
  • 501b606: 8298725: Add BitMap support for reverse iteration
  • 9764948: 8273986: JEditorPane HTML Demo - Accessibility issues
  • 5727610: 8304353: Add lib-test tier1 testing in GHA
  • d8ba227: 8304069: ClassFileParser has ad-hoc hashtables
  • 9a8a60f: 8304833: (fc) Remove dead code in sun.nio.ch.FileChannelImpl::implCloseChannel
  • f96aee7: 8291154: Create a non static nested class without enclosing class throws VerifyError
  • ... and 30 more: https://git.openjdk.org/jdk/compare/ddf1e34c1a0815e8677212f1a7860ca7cf9fc2c9...master

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot added the integrated Pull request has been integrated label Mar 27, 2023
@openjdk openjdk bot closed this Mar 27, 2023
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Mar 27, 2023
@openjdk
Copy link

openjdk bot commented Mar 27, 2023

@djelinski Pushed as commit a5ffa07.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

@djelinski djelinski deleted the server-exceptions branch March 27, 2023 05:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
integrated Pull request has been integrated net net-dev@openjdk.org
Development

Successfully merging this pull request may close these issues.

3 participants