Skip to content

Fix ReferenceCountedFutureImpl to avoid using FirestoreInternal after its deletion. #585

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

Merged
merged 3 commits into from
Jul 29, 2021

Conversation

dconeybe
Copy link
Contributor

This fixes a crash on Android that occurs if the Firestore instance is deleted from an "OnCompletion" handler attached to a Future returned from RunTransaction(). The issue is that in the bowels on the code that manages Future objects it will end up using a deleted FirestoreInternal object when the completion completes. The fix is to null out the FirestoreInternal pointer when it is deleted and avoid using it thereafter.

This fix also fixes a crash that was occurring in SourceTests. Those tests are re-enabled by this PR.

@dconeybe dconeybe self-assigned this Jul 29, 2021
@google-cla google-cla bot added the cla: yes label Jul 29, 2021
@dconeybe dconeybe added the tests-requested: quick Trigger a quick set of integration tests. label Jul 29, 2021
@github-actions github-actions bot added tests: in-progress This PR's integration tests are in progress. and removed tests-requested: quick Trigger a quick set of integration tests. labels Jul 29, 2021
@github-actions
Copy link

github-actions bot commented Jul 29, 2021

✅  Integration test succeeded!

Requested by @dconeybe on commit b050c27
Last updated: Thu Jul 29 15:57 PDT 2021
View integration test log & download artifacts

@github-actions github-actions bot added the tests: succeeded This PR's integration tests succeeded. label Jul 29, 2021
@firebase-workflow-trigger firebase-workflow-trigger bot removed the tests: in-progress This PR's integration tests are in progress. label Jul 29, 2021
@dconeybe dconeybe requested a review from var-const July 29, 2021 18:16
@dconeybe dconeybe assigned var-const and unassigned dconeybe Jul 29, 2021
var-const
var-const previously approved these changes Jul 29, 2021
* Same as `Run()` except that it only invokes the given callback if the
* `FirestoreInternal` pointer is non-null.
*/
void RunIfValid(std::function<void(FirestoreInternal*)> callback) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: because this code is not storing the callback, it can be passed by a const reference.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd suggest passing FirestoreInternal to the callback by reference, to show that it is guaranteed to be valid (not null) if the callback is invoked.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

* deleted) for the duration of the callback's execution.
*
* If this method is invoked concurrently then calls will be serialized in
* an undefined order. Recursive calls of this method are allowed and will not
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: consider s/are allowed/are allowed on the same thread/.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@var-const var-const assigned dconeybe and unassigned var-const Jul 29, 2021
* Change `std::function<void(FirestoreInternal*)>` to a const reference.
* Change the argument in the `std::function` from `FirestoreInternal*` to `FirestoreInternal&`.
* Improve docs: s/are allowed/are allowed on the same thread/.
@github-actions github-actions bot dismissed var-const’s stale review July 29, 2021 19:16

🍞 Dismissed stale approval on external PR.

};

protected:
void AssertCreatesValidFutures(Env& env,

Choose a reason for hiding this comment

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

⚠️ Lint warning: Is this a non-const reference? If so, make const or use a pointer: Env& env


protected:
void AssertCreatesValidFutures(Env& env,
PromiseFactory<AsyncFn>& promise_factory) {

Choose a reason for hiding this comment

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

⚠️ Lint warning: Is this a non-const reference? If so, make const or use a pointer: PromiseFactory<AsyncFn>& promise_factory

EXPECT_EQ(future.status(), FutureStatus::kFutureStatusComplete);
}

void AssertCreatesInvalidFutures(Env& env,

Choose a reason for hiding this comment

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

⚠️ Lint warning: Is this a non-const reference? If so, make const or use a pointer: Env& env

}

void AssertCreatesInvalidFutures(Env& env,
PromiseFactory<AsyncFn>& promise_factory) {

Choose a reason for hiding this comment

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

⚠️ Lint warning: Is this a non-const reference? If so, make const or use a pointer: PromiseFactory<AsyncFn>& promise_factory

@@ -3,11 +3,8 @@
#include "firebase/firestore.h"

#include <algorithm>
#include <future>

Choose a reason for hiding this comment

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

⚠️ Lint warning: <future> is an unapproved C++11 header.

@@ -7,6 +7,7 @@
#include <functional>
#include <list>
#include <memory>
#include <mutex>

Choose a reason for hiding this comment

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

⚠️ Lint warning: <mutex> is an unapproved C++11 header.

impl_->Complete(handle_, error_code, status_message);
});
if (completion_ != nullptr) {
completion_->CompleteWith(error_code, status_message, nullptr);
}
delete this;
}

virtual void SucceedWithResult(jni::Env& env,

Choose a reason for hiding this comment

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

⚠️ Lint warning: Is this a non-const reference? If so, make const or use a pointer: jni::Env& env

}
delete this;
}

virtual void SucceedWithResult(jni::Env& env,
const jni::Object& result) = 0;
const jni::Object& result,
FirestoreInternal& firestore) = 0;

Choose a reason for hiding this comment

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

⚠️ Lint warning: Is this a non-const reference? If so, make const or use a pointer: FirestoreInternal& firestore

@dconeybe dconeybe requested a review from var-const July 29, 2021 19:17
@dconeybe dconeybe assigned var-const and unassigned dconeybe Jul 29, 2021
@var-const var-const assigned dconeybe and unassigned var-const Jul 29, 2021
@dconeybe dconeybe merged commit b050c27 into main Jul 29, 2021
@dconeybe dconeybe deleted the dconeybe/ReferenceCountedFutureImplFix branch July 29, 2021 20:56
@github-actions github-actions bot added tests: in-progress This PR's integration tests are in progress. and removed tests: succeeded This PR's integration tests succeeded. labels Jul 29, 2021
@github-actions github-actions bot added the tests: succeeded This PR's integration tests succeeded. label Jul 29, 2021
@firebase-workflow-trigger firebase-workflow-trigger bot removed the tests: in-progress This PR's integration tests are in progress. label Jul 29, 2021
@firebase firebase locked and limited conversation to collaborators Aug 29, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api: firestore cla: yes tests: succeeded This PR's integration tests succeeded.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants