reconcilable_result_builder: don't aggrevate out-of-memory condition during recovery

Consider an unpaged query that consumes all of available memory, despite
fea5067dfa which limits them (perhaps the
user raised the limit, or this is a system query). Eventually we will see a
bad_alloc which will abort the query and destroy this reconcilable_result_builder.

During destruction, we first destroy _memory_accounter, and then _result.
Destroying _memory_accounter resumes some continuations which can then
allocate memory synchronously when increasing the task queue to accomodate
them. We will then crash. Had we not crashed, we would immediately afterwards
release _result, freeing all the memory that we would ever need.

Fix by making _result the last member, so it is freed first.

Fixes #7240.
This commit is contained in:
Avi Kivity
2020-09-15 16:44:01 +03:00
committed by Tomasz Grabiec
parent 6e10f2b530
commit 9421cfded4

View File

@@ -140,15 +140,16 @@ class reconcilable_result_builder {
const schema& _schema;
const query::partition_slice& _slice;
utils::chunked_vector<partition> _result;
uint64_t _live_rows{};
bool _return_static_content_on_partition_with_no_rows{};
bool _static_row_is_alive{};
uint64_t _total_live_rows = 0;
query::result_memory_accounter _memory_accounter;
stop_iteration _stop;
std::optional<streamed_mutation_freezer> _mutation_consumer;
uint64_t _live_rows{};
// make this the last member so it is destroyed first. #7240
utils::chunked_vector<partition> _result;
public:
reconcilable_result_builder(const schema& s, const query::partition_slice& slice,
query::result_memory_accounter&& accounter)