-
Notifications
You must be signed in to change notification settings - Fork 7
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 possibly huge memory leak caused by long lived CancellableManagerProvider #213
Fix possibly huge memory leak caused by long lived CancellableManagerProvider #213
Conversation
A long lived CancellableManagerProvider could easily end up with very many “cancelled” Cancellable in it’s internal CancellableManager because this is only cleared when the Provider itself is cancelled. This can cause huge memory leaks in some cases, for example in the DebounceProcessor Since there is only ever one “not cancelled” CancellableManager provided by the CancellableManagerProvider, there is actually no need to keep the previously provided, now cancelled, CancellableManager. We now simply use the internalCancellableManagerRef. Also took the oportunity to make cancelPreviousAndCreate hopefully atomic be exposing and using getAndSet on AtomicReference
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this change we change the following behavior: if I create a new CancellableManger and the provider has been cancelled then the returned manager needs to be cancelled.
cancellableManager.add(it) | ||
return CancellableManager().also { cancellableManager -> | ||
internalCancellableManagerRef.getAndSet(cancellableManager).cancel() | ||
serialQueue.dispatch { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The usage of the serialQueue is to ensure sequential cancellation of currently returned ref
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This essentially mimicks the CancellableManager internal implementation to be on the safe side
} | ||
} | ||
|
||
override fun cancel() { | ||
cancellableManager.cancel() | ||
serialQueue.dispatch { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The usage of the serialQueue is to ensure sequential cancellation of currently returned ref
Description
A long lived CancellableManagerProvider could easily end up with very many “cancelled” Cancellable in it’s internal CancellableManager because this is only cleared when the Provider itself is cancelled.
This can cause huge memory leaks in some cases, for example in the DebounceProcessor
Since there is only ever one “not cancelled” CancellableManager provided by the CancellableManagerProvider, there is actually no need to keep the previously provided, now cancelled, CancellableManager.
We now simply use the internalCancellableManagerRef.
Also took the oportunity to make cancelPreviousAndCreate hopefully atomic be exposing and using getAndSet on AtomicReference
Motivation and Context
In certain realtime application, usage of
debounce()
on long lived, shared publishers could cause immense memory leaksHow Has This Been Tested?
Types of changes