Skip to content

HTTP/2: Prevent memory leak when trying to create new streams on a connection that received a GOAWAY.#9674

Merged
normanmaurer merged 3 commits intonetty:4.1from
millems:http-2-frame-codec-memory-leak
Oct 17, 2019
Merged

HTTP/2: Prevent memory leak when trying to create new streams on a connection that received a GOAWAY.#9674
normanmaurer merged 3 commits intonetty:4.1from
millems:http-2-frame-codec-memory-leak

Conversation

@millems
Copy link
Copy Markdown
Contributor

@millems millems commented Oct 15, 2019

Motivation:

In #8692, Http2FrameCodec was updated to keep track of all "being initialized" streams, allocating memory before initialization begins, and releasing memory after initialization completes successfully.

In some instances where stream initialization fails (e.g. because this connection has received a GOAWAY frame), this memory is never released.

Modifications:

This change updates the Http2FrameCodec to use a separate promise for monitoring the success of sending HTTP2 headers. When sending of headers fails, we now make sure to release memory allocated for stream initialization.

Result:

After this change, failures in writing HTTP2 Headers (e.g. because this connection has received a GOAWAY frame) will no longer leak memory.

…nnection that received a GOAWAY.

Motivation:

In netty#8692, `Http2FrameCodec` was
updated to keep track of all "being initialized" streams, allocating
memory before initialization begins, and releasing memory after
initialization completes successfully.

In some instances where stream initialization fails (e.g. because this
connection has received a GOAWAY frame), this memory is never released.

Modifications:

This change updates the `Http2FrameCodec` to use a separate promise
for monitoring the success of sending HTTP2 headers. When sending of
headers fails, we now make sure to release memory allocated for stream
initialization.

Result:

After this change, failures in writing HTTP2 Headers (e.g. because this
connection has received a GOAWAY frame) will no longer leak memory.
@netty-bot
Copy link
Copy Markdown

Can one of the admins verify this patch?

Copy link
Copy Markdown
Member

@normanmaurer normanmaurer left a comment

Choose a reason for hiding this comment

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

A few nits but generally LGTM!

@normanmaurer
Copy link
Copy Markdown
Member

@millems can you please also sign our icla: https://netty.io/s/icla

@normanmaurer
Copy link
Copy Markdown
Member

@netty-bot test this please

@njhill
Copy link
Copy Markdown
Member

njhill commented Oct 16, 2019

@millems probably I'm missing something but why is a separate promise needed? Couldn't we just add a listener to the existing promise?

@millems
Copy link
Copy Markdown
Contributor Author

millems commented Oct 16, 2019

@njhill Using a separate promise was intended to be defensive, and only performing the cleanup if the send-headers failed.

I was concerned about the following scenario:

  1. sendHeaders succeeds
  2. Something fails the original promise for an unrelated issue
  3. The frameStreamToInitializeMap entry is removed because of that failure,
  4. The onStreamAdded is still invoked, because the sendHeaders suceeded and the stream was created
  5. The onStreamAdded doesn't initialize the stream correctly because the original promise was failed.

Let me know if this concern is unfounded, and I can remove the additional future.

@millems
Copy link
Copy Markdown
Contributor Author

millems commented Oct 16, 2019

@normanmaurer Will review comments and address. CLA was reviewed and signed yesterday. Let me know if it's not on record and I can go again.

@normanmaurer
Copy link
Copy Markdown
Member

@millems I think it will be good enough to just attach to the "original" promise as @njhill suggested

@normanmaurer
Copy link
Copy Markdown
Member

@millems all good... I somehow missed it 🤦‍♂

1. Assert channel.finishAndReleaseAll() returns false.
2. Attach failure detection to original future, instead of a separate future.
3. Use ChannelListener instead of GenericFutureListener
4. Note that numInitializingStreams is for testing.
@millems
Copy link
Copy Markdown
Contributor Author

millems commented Oct 16, 2019

Addressed change requests.

@normanmaurer
Copy link
Copy Markdown
Member

@netty-bot test this please

@normanmaurer
Copy link
Copy Markdown
Member

@netty-bot test this please

@normanmaurer normanmaurer added this to the 4.1.43.Final milestone Oct 17, 2019
Copy link
Copy Markdown
Member

@normanmaurer normanmaurer left a comment

Choose a reason for hiding this comment

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

@millems thanks a lot for your work... :)

@normanmaurer normanmaurer merged commit bbc34d0 into netty:4.1 Oct 17, 2019
normanmaurer pushed a commit that referenced this pull request Oct 17, 2019
…nnection that received a GOAWAY. (#9674)

Motivation:

In #8692, `Http2FrameCodec` was
updated to keep track of all "being initialized" streams, allocating
memory before initialization begins, and releasing memory after
initialization completes successfully.

In some instances where stream initialization fails (e.g. because this
connection has received a GOAWAY frame), this memory is never released.

Modifications:

This change updates the `Http2FrameCodec` to use a separate promise
for monitoring the success of sending HTTP2 headers. When sending of
headers fails, we now make sure to release memory allocated for stream
initialization.

Result:

After this change, failures in writing HTTP2 Headers (e.g. because this
connection has received a GOAWAY frame) will no longer leak memory.
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.

4 participants