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 cancelation leak in fromFuture, fromFutureCancelable #3892

Merged
merged 12 commits into from
Nov 23, 2023

Conversation

TimWSpence
Copy link
Member

@TimWSpence TimWSpence commented Nov 9, 2023

Fix leak in fromFutureCancelable and fromFuture. Addresses #3891

@TimWSpence TimWSpence changed the base branch from series/3.x to series/3.5.x November 9, 2023 17:33
async[A](cb => as(delay(fut.onComplete(t => cb(t.toEither))), Some(fin)))
}
async[A] { cb =>
flatMap(futCancel) {
Copy link
Member

Choose a reason for hiding this comment

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

I think we have to use uncancelable+poll. Otherwise starting the Future with futCancel is not cancelable, and it can be. It's only after we've started it, that we need guarantee the async is setup appropriately.

Copy link
Member

Choose a reason for hiding this comment

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

I hope that is sufficient anyway, otherwise we'd have to drop down to cont 😬

Copy link
Member Author

Choose a reason for hiding this comment

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

Well I did only say that I'd fix the leak 😛

Yeah I was wondering about that as I wrote it. I'll give it a go with uncancelable/poll. Although I did notice that in AsyncPlatform#fromCompletableFuture we changed it to use cont. I don't suppose you remember why?

Copy link
Member

Choose a reason for hiding this comment

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

I don't suppose you remember why?

That's because the cancelation protocol for CompletableFuture is more complex: even if you request cancelation, it may indicate to you that it hasn't canceled in which case you need to fallback to waiting for the result. The best way to express this is with cont.

(Aside, but CE doesn't really handle this well, we still have leaks even in the cont-based implementation #3474).

@TimWSpence
Copy link
Member Author

@armanbilge I've updated now. It looks a bit weird to me but I think this has the correct behaviour? The construction of the future should not prohibit cancelation (by being uncanelable) if some part of the provided future construction supports it so we just want to make the flatMap boundary before we register the future with the async node uncancelable.

I'm not sure about fromFuture - we can't cancel there so what is the desired behaviour? Leak the future on cancelation or make it uncancelable?

@armanbilge
Copy link
Member

I've updated now. It looks a bit weird to me but I think this has the correct behaviour?

We can add some tests, that will help us understand if we got it right :)

@TimWSpence
Copy link
Member Author

I've updated now. It looks a bit weird to me but I think this has the correct behaviour?

We can add some tests, that will help us understand if we got it right :)

pfft I don't write bugs 😛

Yeah I'll do that. What do you think about the semantics of fromFuture? Should we leak it or block till it completes?

@armanbilge
Copy link
Member

armanbilge commented Nov 17, 2023

Should we leak it or block till it completes?

Absolutely never leak, Future is not cancelable so we just have to block until it completes. This was the major bugfix released in CE v3.5.0.

@TimWSpence
Copy link
Member Author

Sorry @armanbilge I realized I wasn't sure where I should put these tests. They don't really feel like law tests but I can't find any other existing Async tests. Should they just go in IOSpec?

@armanbilge
Copy link
Member

I can't find any other existing Async tests

https://github.com/typelevel/cats-effect/blob/44545879b453c9a9b91d5d3c472b58b4ab04adb1/tests/shared/src/test/scala/cats/effect/kernel/AsyncSpec.scala

https://github.com/typelevel/cats-effect/blob/44545879b453c9a9b91d5d3c472b58b4ab04adb1/tests/jvm/src/test/scala/cats/effect/kernel/AsyncPlatformSpec.scala

Should they just go in IOSpec

I guess that's fine too. It's all kind of a mess, in theory there is a distinction between tests of the Async typeclass itself and its default implementations and IO-specific tests (e.g. we overwrote Async default implementations).

@TimWSpence
Copy link
Member Author

I can't find any other existing Async tests

https://github.com/typelevel/cats-effect/blob/44545879b453c9a9b91d5d3c472b58b4ab04adb1/tests/shared/src/test/scala/cats/effect/kernel/AsyncSpec.scala

https://github.com/typelevel/cats-effect/blob/44545879b453c9a9b91d5d3c472b58b4ab04adb1/tests/jvm/src/test/scala/cats/effect/kernel/AsyncPlatformSpec.scala

Should they just go in IOSpec

I guess that's fine too. It's all kind of a mess, in theory there is a distinction between tests of the Async typeclass itself and its default implementations and IO-specific tests (e.g. we overwrote Async default implementations).

Oh yeah AsyncSpec isn't actually tied to the laws tests, it just currently doesn't run any other tests 🤦

"fromFuture" should {
"backpressure on cancelation" in real {
// a non-cancelable, never-completing Future
def mkf() = Promise[Unit]().future
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
def mkf() = Promise[Unit]().future
def mkf() = Future.never

@TimWSpence TimWSpence marked this pull request as ready for review November 23, 2023 17:26
Copy link
Member

@djspiewak djspiewak left a comment

Choose a reason for hiding this comment

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

Nice catch!

@djspiewak djspiewak merged commit 5794542 into typelevel:series/3.5.x Nov 23, 2023
27 of 32 checks passed
@TimWSpence
Copy link
Member Author

Nice catch!

Thanks Daniel! :)

@armanbilge armanbilge changed the title 3891 fix future leak Fix cancelation leak in fromFuture, fromFutureCancelable Jan 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants