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

Support stream cancellation #142

Closed

Conversation

FinleyMcIlwaine
Copy link
Collaborator

We now support stream cancellation via the OutBodyIface API's outBodyCancel function. Some care was taken to ensure that cancelling idle streams does not result in protocol errors. In particular, outBodyCancel will wait until either the headers have been sent successfully or an exception occurs. If we aren't totally sure that the headers are sent, we won't send RST_STREAM.

We now support stream cancellation via the `OutBodyIface` API's `outBodyCancel`
function. Some care was taken to ensure that cancelling idle streams does not
result in protocol errors. In particular, `outBodyCancel` will wait until either
the headers have been sent successfully or an exception occurs. If we aren't
totally sure that the headers are sent, we won't send `RST_STREAM`.
@FinleyMcIlwaine
Copy link
Collaborator Author

@kazu-yamamoto Could you please request a review from @edsko on this as well? Thank you!

@kazu-yamamoto kazu-yamamoto requested a review from edsko August 27, 2024 00:37
Network/HTTP2/Client/Run.hs Outdated Show resolved Hide resolved
Network/HTTP2/Client/Run.hs Outdated Show resolved Hide resolved
Network/HTTP2/Client/Run.hs Outdated Show resolved Hide resolved
Network/HTTP2/Client/Run.hs Outdated Show resolved Hide resolved
Network/HTTP2/H2/Sender.hs Outdated Show resolved Hide resolved
Network/HTTP2/Server/Worker.hs Outdated Show resolved Hide resolved
@edsko
Copy link
Collaborator

edsko commented Aug 28, 2024

This depends on kazu-yamamoto/http-semantics#11 .

Copy link
Collaborator

@edsko edsko left a comment

Choose a reason for hiding this comment

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

We realized this is not quite right. We will change the PR.

The 'outputQ' invariant is what guarantees we won't send @RST_STREAM@ frames
ahead of some still-enqueued data frames for a stream.

Additionally, the previous commit was unnecessarily tracking whether headers had
been sent on a stream to deal with a bug which we have now *actually* fixed, so
we no longer track whether headers are sent per-stream as we were.
Track whether a stream is finished or cancelled in a `TVar` rather than an
`IORef`, and update that `TVar` in a single transaction which also writes the
appropriate http-semantics `StreamingChunk` to the queue.
Copy link
Collaborator

@edsko edsko left a comment

Choose a reason for hiding this comment

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

This looks good to me now, and I think we could merge this now as-is, but I think we can make a two minor improvements (as well as remove that redundant constructor, mentioned above):

  1. I wonder what should happen with outBodyPush etc once the stream is finished. This should be considered a user bug, I think, but it might be good to detect these cases and throw an exception.
  2. Let's try and avoid the redundancy between the two outBodyIface constructions (all the more important after we also implement (1).

@@ -208,6 +214,7 @@ data HTTP2Error
| StreamErrorIsSent ErrorCode StreamId ReasonPhrase
| BadThingHappen E.SomeException
| GoAwayIsSent
| RSTStreamIsSent
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this a leftover from a previous attempt? Doesn't seem to be used anywhere?

There was duplicated code in `Network.HTTP2.Client.Run` and
`Network.HTTP2.Server.Worker` to construct a `OutBodyIface`. We have moved that
to a dedicated module. We also now throw exceptions when a push or flush is
attempted on a concluded stream.
Copy link
Collaborator

@edsko edsko left a comment

Choose a reason for hiding this comment

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

LGTM! @kazu-yamamoto , this PR and kazu-yamamoto/http-semantics#11 and now ready for your review.

@kazu-yamamoto kazu-yamamoto self-requested a review August 29, 2024 21:47
@kazu-yamamoto
Copy link
Owner

I have released http2-semantics and run CI again.

Copy link
Owner

@kazu-yamamoto kazu-yamamoto left a comment

Choose a reason for hiding this comment

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

LGTM

  • added http-semantics >= 0.2.1
  • formatted with fourmolu

kazu-yamamoto added a commit that referenced this pull request Aug 29, 2024
@kazu-yamamoto
Copy link
Owner

A new version has been released.

@edsko edsko mentioned this pull request Oct 23, 2024
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Jan 30, 2025
# ChangeLog for http2

## 5.3.9

* Using `ThreadManager` of `time-manager`.

## 5.3.8

* `forkManagedTimeout` ensures that only one asynchronous exception is
  thrown. Fixing the thread leak via `Weak ThreadId` and `modifyTVar'`.
  [#156](kazu-yamamoto/http2#156)

## 5.3.7

* Using `withHandle` of time-manager.
* Getting `Handle` for each thread.
* Providing allocSimpleConfig' to enable customizing WAI tiemout manager.
* Monitor option (-m) for h2c-client and h2c-server.

## 5.3.6

* Making `runIO` friendly with the new synchronism mechanism.
  [#152](kazu-yamamoto/http2#152)
* Re-throwing asynchronous exceptions to prevent thread leak.
* Simplifying the synchronism mechanism between workers and the sender.
  [#148](kazu-yamamoto/http2#148)

## 5.3.5

* Using `http-semantics` v0.3.
* Deprecating `numberOfWorkers`.
* Removing `unliftio`.
* Avoid `undefined` in client.
  [#146](kazu-yamamoto/http2#146)

## 5.3.4

* Support stream cancellation
  [#142](kazu-yamamoto/http2#142)

## 5.3.3

* Enclosing IPv6 literal authority with square brackets.
  [#143](kazu-yamamoto/http2#143)

## 5.3.2

* Avoid unnecessary empty data frames at end of stream
  [#140](kazu-yamamoto/http2#140)
* Removing unnecessary API from ServerIO

## 5.3.1

* Fix treatment of async exceptions
  [#138](kazu-yamamoto/http2#138)
* Avoid race condition
  [#137](kazu-yamamoto/http2#137)

## 5.3.0

* New server architecture: spawning worker on demand instead of the
  worker pool. This reduce huge numbers of threads for streaming into
  only 2. No API changes but workers do not terminate quicly. Rather
  workers collaborate with the sender after queuing a response and
  finish after all response data are sent.
* All threads are labeled with `labelThread`. You can see them by
  `listThreas` if necessary.

## 5.2.6

* Recover rxflow on closing.
  [#126](kazu-yamamoto/http2#126)
* Fixing ClientSpec for stream errors.
* Allowing negative window. (h2spec http2/6.9.2)
* Update for latest http-semantics
  [#122](kazu-yamamoto/http2#124)

## 5.2.5

* Setting peer initial window size properly.
  [#123](kazu-yamamoto/http2#123)

## 5.2.4

* Update for latest http-semantics
  [#122](kazu-yamamoto/http2#122)
* Measuring performance concurrently for h2c-client

## 5.2.3

* Update for latest http-semantics
  [#120](kazu-yamamoto/http2#120)
* Enable containers 0.7 (ghc 9.10)
  [#117](kazu-yamamoto/http2#117)

## 5.2.2

* Mark final chunk as final
  [#116](kazu-yamamoto/http2#116)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants