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

Fix Resource Leak In Jetty #4783

Merged
merged 7 commits into from May 10, 2021

Conversation

isomarcte
Copy link
Member

We had a resource leak in Jetty due to us not calling .destroy in the def resource after the server terminated. Fixing this leak was a bit complicated.

By default, Jetty will terminate the provided ThreadPool as part of the resource cleanup in .destroy. Since we were sharing the ThreadPool in the builder, this would cause any new invocations of def resource to fail as the underlying ThreadPool will have now been terminated.

To fix this problem we now use a Resource[F, ThreadPool] which will ensure that we get a fresh ThreadPool on each invocation, as well as ensuring proper shutdown semantics. We have to keep around the old ThreadPool for binary compatibility. In order to avoid starting two ThreadPool instances we introduce a LazyThreadPool which should never actually create a ThreadPool (I had to leave some ThreadPool type here and I didn't want to use null or anything that would throw if it got accidentally accessed).

If someone explicitly sets the ThreadPool with the deprecated withThreadPool method, then we wrap it in UndestroyableThreadPool which hides the join method and thus preserves the old behavior allowing the ThreadPool to be shared across multiple invocations of def resource while still allowing us to cleanup all the other resources.

JettyLifeCycle provides utilities which lift the Jetty interfaces LifeCycle and Destroyable into a Resource. These are not public to keep the binary compatibility surface as small as possible. In order to allow users to customize the ThreadPool a subset of JettyLifeCycle is exposed in JettyThreadPools.

We had a resource leak in Jetty due to us not calling `.destroy` in the `def resource` after the server terminated. Fixing this leak was a bit complicated.

By default, Jetty will terminate the provided `ThreadPool` as part of the resource cleanup in `.destroy`. Since we were sharing the `ThreadPool` in the builder, this would cause any new invocations of `def resource` to fail as the underlying `ThreadPool` will have now been terminated.

To fix this problem we now use a `Resource[F, ThreadPool]` which will ensure that we get a fresh `ThreadPool` on each invocation, as well as ensuring proper shutdown semantics. We have to keep around the old `ThreadPool` for binary compatibility. In order to avoid starting _two_ `ThreadPool` instances we introduce a `LazyThreadPool` which _should_ never actually create a `ThreadPool` (I had to leave some `ThreadPool` type here and I didn't want to use `null` or anything that would throw if it got accidentally accessed).

If someone explicitly sets the `ThreadPool` with the deprecated `withThreadPool` method, then we wrap it in `UndestroyableThreadPool` which hides the `join` method and thus preserves the old behavior allowing the `ThreadPool` to be shared across multiple invocations of `def resource` while still allowing us to cleanup all the other resources.

`JettyLifeCycle` provides utilities which lift the Jetty interfaces `LifeCycle` and `Destroyable` into a `Resource`. These are not public to keep the binary compatibility surface as small as possible. In order to allow users to customize the `ThreadPool` a subset of `JettyLifeCycle` is exposed in `JettyThreadPools`.
@rossabaker rossabaker added bug Determined to be a bug in http4s module:jetty-server labels Apr 25, 2021
@rossabaker rossabaker added this to the 0.21.23 milestone Apr 25, 2021
@hamnis
Copy link
Contributor

hamnis commented May 5, 2021

needs a conflict resolving, otherwise good

@isomarcte
Copy link
Member Author

@hamnis conflicts are resolved. Thanks for the review!

@hamnis hamnis merged commit dcb2d2b into http4s:series/0.21 May 10, 2021
@aeons aeons mentioned this pull request May 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Determined to be a bug in http4s module:jetty-server
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants