Skip to content

Commit 4fdf107

Browse files
jbmscopybara-github
authored andcommitted
Fix reference counting bug in FutureLink
PiperOrigin-RevId: 752577485 Change-Id: I8cdc8d2d8f25b01142921445eff6531a115246ca
1 parent 026d979 commit 4fdf107

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

tensorstore/util/future_impl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,11 @@ struct FutureLinkPropagateFirstErrorPolicy {
949949
static bool OnFutureReady(FutureStateBase* future_state,
950950
FutureState<PromiseValue>* promise_state) {
951951
if (future_state->has_value()) return true;
952+
// Hold reference to `promise_state` while calling `SetResult`.
953+
// Otherwise, calling `promise_state->SetResult` can trigger
954+
// `promise_state` being destroyed while `SetResult` is still
955+
// invoking callbacks.
956+
PromiseStatePointer promise_state_ptr(promise_state);
952957
promise_state->SetResult(future_state->status());
953958
return false;
954959
}

tensorstore/util/future_test.cc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,6 +1881,25 @@ TEST(FutureTest, Live) {
18811881
registry.Collect("/tensorstore/futures/live")->values[0].value));
18821882
}
18831883

1884+
TEST(FutureTest, LinkValueTwoErrors) {
1885+
auto [promise3, future3] = PromiseFuturePair<void>::Make();
1886+
auto [promise1, future1] = PromiseFuturePair<void>::Make();
1887+
auto [promise2, future2] = PromiseFuturePair<void>::Make();
1888+
{
1889+
auto [promise, future] = PromiseFuturePair<int64_t>::Make();
1890+
1891+
LinkValue([](Promise<int64_t> promise, ReadyFuture<void> future1,
1892+
ReadyFuture<void> future2) { promise.SetResult(5); },
1893+
std::move(promise), std::move(future1), std::move(future2));
1894+
1895+
LinkResult(std::move(promise3), std::move(future));
1896+
}
1897+
1898+
promise1.SetResult(absl::FailedPreconditionError(""));
1899+
1900+
EXPECT_FALSE(future3.result().ok());
1901+
}
1902+
18841903
static void BM_Future_ExecuteWhenReady(benchmark::State& state) {
18851904
int num_callbacks = state.range(0);
18861905
for (auto _ : state) {

0 commit comments

Comments
 (0)