File tree Expand file tree Collapse file tree 2 files changed +24
-0
lines changed
Expand file tree Collapse file tree 2 files changed +24
-0
lines changed Original file line number Diff line number Diff 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 }
Original file line number Diff line number Diff 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+
18841903static void BM_Future_ExecuteWhenReady (benchmark::State& state) {
18851904 int num_callbacks = state.range (0 );
18861905 for (auto _ : state) {
You can’t perform that action at this time.
0 commit comments