Skip to content

Commit

Permalink
fix: Memory leak due to mishandling of event registry objects after c…
Browse files Browse the repository at this point in the history
…leanup
  • Loading branch information
steilerDev committed Aug 10, 2023
1 parent fa20211 commit 186d668
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 7 deletions.
1 change: 0 additions & 1 deletion app/src/app/icloud-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ abstract class iCloudApp extends iCPSApp {
*/
async clean() {
await ResourceManager.network.resetSession();
ResourceManager.events(this.icloud.mfaServer).removeListeners();
ResourceManager.events(this.icloud.photos).removeListeners();
ResourceManager.events(this.icloud).removeListeners();
await this.releaseLibraryLock();
Expand Down
25 changes: 19 additions & 6 deletions app/src/lib/resource-manager/event-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,29 @@ export class EventManager {
return this;
}

const registeredListeners = event === undefined
? this._eventRegistry.get(source)
: this._eventRegistry.get(source).filter(registryObject => registryObject.event === event);
// We need to remove reference to the listener from the registry to avoid memory leaks
// Storing non-removed listeners in a new array and replacing the old one with it
const updatedSourceRegistry: EventRegistryObject[] = [];

let removedListenerCount = 0;
for (const registryObject of this._eventRegistry.get(source)) {
if (event === undefined || registryObject.event === event) { // Removing listener and not pushing to new array
this._eventBus.removeListener(registryObject.event, registryObject.listener);
removedListenerCount++;
} else { // Keeping listener and pushing to new array
updatedSourceRegistry.push(registryObject);
}
}

ResourceManager.logger(this).debug(`Removing ${registeredListeners.length} listeners for source ${source.constructor.name}`);
ResourceManager.logger(this).debug(`Removed ${removedListenerCount} listeners for source ${source.constructor.name}`);

for (const registeredListener of registeredListeners) {
this._eventBus.removeListener(registeredListener.event, registeredListener.listener);
if (updatedSourceRegistry.length === 0) {
ResourceManager.logger(this).debug(`No more listeners for source ${source.constructor.name} registered`);
this._eventRegistry.delete(source);
return this;
}

this._eventRegistry.set(source, updatedSourceRegistry);
return this;
}
}
Expand Down

0 comments on commit 186d668

Please sign in to comment.