Skip to content

Firestore: Potential memory leak in snapshot listener callbacks. #49

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

Closed
dconeybe opened this issue Aug 13, 2021 · 1 comment
Closed
Assignees

Comments

@dconeybe
Copy link
Contributor

There is a memory leak in Firestore that should be fixed regarding snapshot callbacks.

Here are the two problematic code snippets:

DocumentReference.DocumentSnapshotsHandler()

[MonoPInvokeCallback(typeof(ListenerDelegate))]
private static void DocumentSnapshotsHandler(int callbackId, IntPtr snapshotPtr,
FirestoreError errorCode, string errorMessage) {
Action<DocumentSnapshotProxy, FirestoreError, string> callback;
if (snapshotListenerCallbacks.TryGetCallback(callbackId, out callback)) {
callback(new DocumentSnapshotProxy(snapshotPtr, true), errorCode, errorMessage);
}
}

Query.QuerySnapshotsHandler()

[MonoPInvokeCallback(typeof(ListenerDelegate))]
private static void QuerySnapshotsHandler(int callbackId, IntPtr snapshotPtr,
FirestoreError errorCode, string errorMessage) {
Action<QuerySnapshotProxy, FirestoreError, string> callback;
if (snapshotListenerCallbacks.TryGetCallback(callbackId, out callback)) {
callback(new QuerySnapshotProxy(snapshotPtr, true), errorCode, errorMessage);
}
}

The IntPtr passed to DocumentSnapshotsHandler()/QuerySnapshotsHandler() is an owning pointer to the underlying C++ object, meaning that C# is responsible for deleting the underlying C++ object. This deletion is looked after by the DocumentSnapshotProxy/QuerySnapshotProxy objects because their cMemoryOwn constructor argument is being specified a value of true. However, these proxy object are created in an "if" block. Therefore, if the "if" block is not entered then ownership of the C++ object will not be claimed and it will never be deleted, creating a memory leak.

Thankfully, this would be a very rare situation that the "if" block would not be entered; however, it should still be fixed for robustness. The fix is to simply create the DocumentSnapshotProxy/QuerySnapshotProxy objects unconditionally, before the "if" block, so that ownership of the C++ object will be claimed and deleted regardless of whether or not the "if" block is executed.

@dconeybe dconeybe self-assigned this Aug 13, 2021
@dconeybe
Copy link
Contributor Author

Fixed by cl/391282781, which is, unfortunately, only visible to Googlers. It will eventually be ported to this repository though.

@firebase firebase locked and limited conversation to collaborators Jun 3, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant