-
Notifications
You must be signed in to change notification settings - Fork 276
Attempt to fix room GC cycle resulting in memory leak #2009
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
Draft
1egoman
wants to merge
10
commits into
main
Choose a base branch
from
room-memory-leak
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
a02ec43
fix: attempt to fix room memory leak
1egoman 198a82f
fix: add missing changeset
1egoman 2199f77
fix: wrap FrameMetadataManager.room in WeakRef to break GC cycle
1egoman c09f2c2
feat: add weak ref polyfill and port frame metadata manager over to u…
1egoman c227fb2
feat: add weak ref wrapper around room e2ee manager reference
1egoman 511964a
feat: add visibilitychange event cleanup
1egoman d2b574d
fix: clear media stream track listener
1egoman ea194e8
fix: null out srcObject before moving to module global pool
1egoman 350e51f
fix: remove this.deviceChangeCleanupController?.abort() from disconnect
1egoman bdc9112
fix: address lint error
1egoman File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| 'livekit-client': patch | ||
| --- | ||
|
|
||
| Fix room GC cycle due to not unregistered devicechange event |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| /** | ||
| * A `WeakRef`-like reference that falls back to a strong reference on runtime | ||
| * environments that do not implement `WeakRef`. | ||
| * | ||
| * This is primarily useful for breaking reference cycles (so an object can be | ||
| * garbage collected once no longer referenced elsewhere) while remaining safe | ||
| * on legacy browsers. On those legacy browsers the fallback reintroduces the | ||
| * strong reference — and therefore the cycle — which is an acceptable trade-off | ||
| * since they typically lack the modern APIs these cycles arise from anyway. | ||
| * | ||
| * Mirrors the `WeakRef` API: call {@link deref} to retrieve the referenced | ||
| * value, which returns `undefined` once it has been collected. | ||
| * | ||
| * @link https://developer.mozilla.org/en-US/docs/Web/API/WeakRef | ||
| */ | ||
| export class WeakRefPolyfill<T extends object> { | ||
| private weak?: WeakRef<T>; | ||
|
|
||
| private strong?: T; | ||
|
|
||
| constructor(value: T) { | ||
| if (typeof WeakRef !== 'undefined') { | ||
| this.weak = new WeakRef(value); | ||
| } else { | ||
| this.strong = value; | ||
| } | ||
| } | ||
|
|
||
| deref(): T | undefined { | ||
| return this.weak ? this.weak.deref() : this.strong; | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
🟡 Device-change listener is never removed on disconnect for legacy browsers, leaking the Room
The device-change listener is no longer unregistered on disconnect (
handleDisconnectatsrc/room/Room.ts:1865-1869) after the explicitremoveEventListenercall was deleted, so on legacy browsers (withoutWeakRef/FinalizationRegistry) the handler permanently retains the Room object.Impact: On legacy browsers, a disconnected Room can never be garbage-collected and continues to react to device-change events.
Legacy-path reference chain keeps Room alive after disconnect
In the constructor (
src/room/Room.ts:395-399), whenRoom.cleanupRegistryis falsy (legacy browsers), the fallback setsonDeviceChange = this.handleDeviceChange— a direct strong reference to the Room instance. The localcleanupControlleris never registered with aFinalizationRegistryand is never aborted, so thesignalpassed toaddEventListeneratsrc/room/Room.ts:402-404never fires.Previously,
handleDisconnectcontained:This line was the only cleanup path for the legacy case. With it removed, the listener persists indefinitely after disconnect, preventing GC of the Room and continuing to invoke
handleDeviceChangeon a disconnected Room.(Refers to lines 1865-1869)
Prompt for agents
Was this helpful? React with 👍 or 👎 to provide feedback.