commitlog: Fix double clearing of _segment_allocating shared_future.
Fixes #10020
Previous fix 445e1d3 tried to close one double invocation, but added
another, since it failed to ensure all potential nullings of the opt
shared_future happened before a new allocator could reset it.
This simplifies the code by making clearing the shared_future a
pre-requisite for resolving its contents (as read by waiters).
Also removes any need for try-catch etc.
Closes #10024
This commit is contained in:
@@ -1626,21 +1626,19 @@ future<db::commitlog::segment_manager::sseg_ptr> db::commitlog::segment_manager:
|
||||
// the old one has terminated with either result or exception.
|
||||
// Do all waiting through the shared_future
|
||||
if (!_segment_allocating) {
|
||||
_segment_allocating.emplace(new_segment().discard_result());
|
||||
}
|
||||
try {
|
||||
co_await _segment_allocating->get_future(timeout);
|
||||
// once we've managed to get a result, any of us, the
|
||||
// shared_future should be released.
|
||||
_segment_allocating = std::nullopt;
|
||||
} catch (timed_out_error&) {
|
||||
throw; // not thrown by new_segment. Just no result yet.
|
||||
} catch (...) {
|
||||
// once we've managed to get a result, any of us, the
|
||||
// shared_future should be released.
|
||||
_segment_allocating = std::nullopt;
|
||||
throw;
|
||||
auto f = new_segment();
|
||||
// must check that we are not already done.
|
||||
if (f.available()) {
|
||||
f.get(); // maybe force exception
|
||||
continue;
|
||||
}
|
||||
_segment_allocating.emplace(f.discard_result().finally([this] {
|
||||
// clear the shared_future _before_ resolving its contents
|
||||
// (i.e. with result of this finally)
|
||||
_segment_allocating = std::nullopt;
|
||||
}));
|
||||
}
|
||||
co_await _segment_allocating->get_future(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user