-
Notifications
You must be signed in to change notification settings - Fork 121
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
Conversation
…rnal after its deletion.
✅ Integration test succeeded!Requested by @dconeybe on commit b050c27 |
* 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) { |
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.
Nit: because this code is not storing the callback, it can be passed by a const reference.
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.
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.
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.
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 |
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.
Nit: consider s/are allowed/are allowed on the same thread/
.
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.
Done.
* 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/.
🍞 Dismissed stale approval on external PR.
}; | ||
|
||
protected: | ||
void AssertCreatesValidFutures(Env& env, |
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.
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) { |
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.
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, |
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.
Is this a non-const reference? If so, make const or use a pointer: Env& env
} | ||
|
||
void AssertCreatesInvalidFutures(Env& env, | ||
PromiseFactory<AsyncFn>& promise_factory) { |
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.
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> |
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.
<future> is an unapproved C++11 header.
@@ -7,6 +7,7 @@ | |||
#include <functional> | |||
#include <list> | |||
#include <memory> | |||
#include <mutex> |
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.
<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, |
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.
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; |
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.
Is this a non-const reference? If so, make const or use a pointer: FirestoreInternal& firestore
This fixes a crash on Android that occurs if the
Firestore
instance is deleted from an "OnCompletion" handler attached to aFuture
returned fromRunTransaction()
. The issue is that in the bowels on the code that managesFuture
objects it will end up using a deletedFirestoreInternal
object when the completion completes. The fix is to null out theFirestoreInternal
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.