Merge 'compaction: handle exception in expected_total_workload' from Aleksandra Martyniuk

expected_total_workload methods of scrub compaction tasks create a vector of table_info based on table names. If any table was already dropped, then the exception is thrown. It leaves table_info in corrupted state and node crashes with `free(): invalid size`.

Return std::nullopt if an exception was thrown to indicate that total workload cannot be found.

Fixes: #25941.

No release branches affected

Closes scylladb/scylladb#25944

* github.com:scylladb/scylladb:
  tasks: get progress of failed task based on children
  compaction: handle exception in expected_total_workload
This commit is contained in:
Botond Dénes
2025-09-17 15:10:19 +03:00
2 changed files with 44 additions and 22 deletions

View File

@@ -718,13 +718,21 @@ future<> scrub_sstables_compaction_task_impl::run() {
}
future<std::optional<double>> scrub_sstables_compaction_task_impl::expected_total_workload() const {
auto table_infos = _column_families | std::views::transform([this] (const auto& cf) {
return table_info{
.name = cf,
.id = _db.local().find_uuid(_status.keyspace, cf)
};
}) | std::ranges::to<std::vector<table_info>>();
co_return _expected_workload = _expected_workload ? _expected_workload : co_await get_keyspace_task_workload(_db, std::move(table_infos));
try {
std::vector<table_info> table_infos;
table_infos.reserve(_column_families.size());
for (const auto& cf : _column_families) {
auto id = _db.local().find_uuid(_status.keyspace, cf);
table_infos.push_back(table_info{
.name = cf,
.id = id
});
}
co_return _expected_workload = _expected_workload ? _expected_workload : co_await get_keyspace_task_workload(_db, std::move(table_infos));
} catch (...) {
// Expected total workload cannot be found.
}
co_return std::nullopt;
}
future<> shard_scrub_sstables_compaction_task_impl::run() {
@@ -739,13 +747,21 @@ future<> shard_scrub_sstables_compaction_task_impl::run() {
}
future<std::optional<double>> shard_scrub_sstables_compaction_task_impl::expected_total_workload() const {
auto table_infos = _column_families | std::views::transform([this] (const auto& cf) {
return table_info{
.name = cf,
.id = _db.find_uuid(_status.keyspace, cf)
};
}) | std::ranges::to<std::vector<table_info>>();
co_return _expected_workload = _expected_workload ? _expected_workload : co_await get_shard_task_workload(_db, std::move(table_infos));
try {
std::vector<table_info> table_infos;
table_infos.reserve(_column_families.size());
for (auto& cf : _column_families) {
auto id = _db.find_uuid(_status.keyspace, cf);
table_infos.push_back(table_info{
.name = cf,
.id = id
});
}
co_return _expected_workload = _expected_workload ? _expected_workload : co_await get_shard_task_workload(_db, std::move(table_infos));
} catch (...) {
// Expected total workload cannot be found.
}
co_return std::nullopt;
}
future<> table_scrub_sstables_compaction_task_impl::run() {
@@ -760,14 +776,20 @@ future<> table_scrub_sstables_compaction_task_impl::run() {
}
future<std::optional<double>> table_scrub_sstables_compaction_task_impl::expected_total_workload() const {
if (!_expected_workload) {
table_info ti{
.name = _status.table,
.id = _db.find_uuid(_status.keyspace, _status.table)
};
_expected_workload = co_await get_table_task_workload(_db, ti);
try {
if (!_expected_workload) {
auto id = _db.find_uuid(_status.keyspace, _status.table);
table_info ti{
.name = _status.table,
.id = id
};
_expected_workload = co_await get_table_task_workload(_db, ti);
}
co_return _expected_workload;
} catch (...) {
// Expected total workload cannot be found.
}
co_return _expected_workload;
co_return std::nullopt;
}
future<> table_reshaping_compaction_task_impl::run() {

View File

@@ -123,7 +123,7 @@ future<std::optional<double>> task_manager::task::impl::expected_total_workload(
}
future<task_manager::task::progress> task_manager::task::impl::get_progress() const {
if (is_done()) {
if (is_complete()) {
co_return co_await _children.get_progress(_status.progress_units);
}