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

Cancel write semantic #12727

Merged
merged 64 commits into from
Feb 27, 2025
Merged

Cancel write semantic #12727

merged 64 commits into from
Feb 27, 2025

Conversation

gregw
Copy link
Contributor

@gregw gregw commented Jan 22, 2025

Added a cancel write/send semantic so that buffers for failed writes need not be removed from the pool

gregw added 2 commits January 22, 2025 17:41

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Provide a write cancel mechanism so that removing pooled buffers can be avoided.
@gregw gregw requested review from sbordet and lorban January 22, 2025 08:09
@gregw
Copy link
Contributor Author

gregw commented Jan 22, 2025

@sbordet can you implement the cancel semantic for http2. @lorban ditto for http3

gregw and others added 6 commits January 22, 2025 12:48
Provide a write cancel mechanism so that removing pooled buffers can be avoided.
…1.x/cancelWrite
Signed-off-by: Ludovic Orban <[email protected]>
@gregw
Copy link
Contributor Author

gregw commented Jan 29, 2025

@sbordet @lorban nudge for actual review

Copy link
Contributor

@sbordet sbordet left a comment

Choose a reason for hiding this comment

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

I am dubious about the H2/h3 implementation; we should talk about it.

@gregw gregw requested review from lorban and sbordet January 31, 2025 15:53
@sbordet
Copy link
Contributor

sbordet commented Jan 31, 2025

@gregw another issue is the use of CountingCallback: it has the semantic to count for successes, but it fails on the first failure.

So it has not the right semantic for the usage that was done in H2 and H3.

gregw added 2 commits January 31, 2025 17:15
@gregw
Copy link
Contributor Author

gregw commented Feb 4, 2025

@gregw another issue is the use of CountingCallback: it has the semantic to count for successes, but it fails on the first failure.

So it has not the right semantic for the usage that was done in H2 and H3.

@sbordet See new static List<Callback> from(Callback callback, Throwable cause, int count) method that replaces CountingCallback

Signed-off-by: Ludovic Orban <[email protected]>
Copy link
Contributor

@lorban lorban left a comment

Choose a reason for hiding this comment

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

I believe the mechanism is sane, but I can't wrap my head around the newly introduced API and how this should all work.

I've attempted to write a test for this functionality (I've pushed it to this PR) and that left me puzzled. We should probably discuss it.

@gregw
Copy link
Contributor Author

gregw commented Feb 12, 2025

@sbordet @lorban have you looked at this recently? Any updates for h2 or h3?

fix flush
Signed-off-by: Ludovic Orban <[email protected]>
@lorban lorban requested a review from sbordet February 24, 2025 10:33
@gregw gregw requested a review from sbordet February 24, 2025 21:40
Signed-off-by: Simone Bordet <[email protected]>
@gregw gregw requested a review from sbordet February 25, 2025 15:08
Added a new Callback.Combination rather than the Callback.collection method
Improved Callback.Combination as an Autocloseable
Improved Callback.Combination as an Autocloseable
Comment on lines 449 to 450
int s = state.getStamp();
Throwable failure = state.getReference();
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you want to take them atomically, so here you should use state.get(int[]).
Likewise in the other places.

Actually, my suggestion of AtomicStampedReference was more to handle the Callback and the counter together... Now that the callback is final, I don't think we need AtomicStampedReference anymore, we can split again failure and counter, as now we just use the counter as the state of all the callbacks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We don't need to take them atomically. If they change between one get and the next, then the CaS will fail anyway. I guess it is only a single volatile lookup, so maybe better... I'll have a look at it

Copy link
Contributor

Choose a reason for hiding this comment

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

I would prefer just AtomicInteger for the counter at this point.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the stamped reference is better. There are still some races with multiple failures that this solves and gives us more deterministic behaviour.

Improved Callback.Combination as an Autocloseable
@gregw gregw requested a review from sbordet February 26, 2025 13:51
@gregw gregw dismissed lorban’s stale review February 26, 2025 13:51

on vacation


// If the stamp is < 0, the combination has not been closed, so we increment, else we decrement.
int n = s < 0 ? s + 1 : s - 1;
if (!state.compareAndSet(failure, combined, s, n))
Copy link
Contributor

Choose a reason for hiding this comment

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

If this CAS fails, is exception combination above safe?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is. Failure will only go from null to non-null once and then stay at that value. So we are not trying to hit a moving target. If the cas fails, then the addSuppressed will not add the same exception again, because they will already be associated. But it will be the same target failure, so the previous addSuppressed was the correct thing to do.

Note, it is because of this slight complex race that I had the failure logic after the CaS, but before the the andThen callback. I think it is safe there as well with less thought needed, but you asked me to move it. I think it is probably better where it is now.

@gregw gregw requested a review from sbordet February 26, 2025 17:44
@gregw
Copy link
Contributor Author

gregw commented Feb 27, 2025

@sbordet I'm going to try to get a clean CI build before merging. I think the failures are flakes or CI issues... but will check.

Also, what is the plan for 12.0.x? Can any of this be backported easily? The h2 reset fix?

@sbordet
Copy link
Contributor

sbordet commented Feb 27, 2025

Plan for 12.0.x is to rely on releaseAndRemove(), as we don't have the onAborted() and complete event separation semantic in 12.0.x IteratingCallback.

@gregw gregw merged commit 43e02a2 into jetty-12.1.x Feb 27, 2025
10 checks passed
@gregw gregw deleted the fix/jetty-12.1.x/cancelWrite branch February 27, 2025 15:43
@wendigo
Copy link

wendigo commented Feb 27, 2025

🎉

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 High Priority
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

ByteBufferPool - all ongoing requests fail when single request is cancelled on HTTP/2
4 participants