Merge 'Do not leak S3 file-uploading parts on exceptions' from Pavel Emelyanov

File uploading code spawns all parts uploading into background. If this "spawning" fails (not the uploading code itself), any fiber that was spawned before is orphaned. It will eventually stop on its own, by while it's alive it may use(-after-free) the do_upload_file object.

Another issue with not handling spawn exception, is that multipart upload object is not aborted in this case. So it's leaked until garbage collector picks it up, which is not critical, but unpleasant.

Closes scylladb/scylladb#21139

* github.com:scylladb/scylladb:
  s3/client: Restore indentation after previous patch
  s3/client: Catch do_upload_file::upload_part() exceptions
This commit is contained in:
Botond Dénes
2024-10-23 10:12:29 +03:00

View File

@@ -1009,19 +1009,22 @@ class client::do_upload_file : private multipart_upload {
future<> multi_part_upload(file&& f, uint64_t total_size, size_t part_size) {
co_await start_upload();
for (size_t offset = 0; offset < total_size; offset += part_size) {
part_size = std::min(total_size - offset, part_size);
s3l.trace("upload_part: {}~{}/{}", offset, part_size, total_size);
co_await upload_part(file{f}, offset, part_size);
}
std::exception_ptr ex;
try {
for (size_t offset = 0; offset < total_size; offset += part_size) {
part_size = std::min(total_size - offset, part_size);
s3l.trace("upload_part: {}~{}/{}", offset, part_size, total_size);
co_await upload_part(file{f}, offset, part_size);
}
co_await finalize_upload();
} catch (...) {
ex = std::current_exception();
}
if (ex) {
if (!_bg_flushes.is_closed()) {
co_await _bg_flushes.close();
}
co_await abort_upload();
std::rethrow_exception(ex);
}