mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-22 07:42:16 +00:00
start_docker_service is a coroutine that took docker_args and image_args by const reference. Its caller start_fake_gcs_server is a regular function that passes temporaries (initializer lists) and immediately returns a future. The temporaries are destroyed when the caller returns, leaving the coroutine holding dangling references. On the first loop iteration this works by luck (memory not yet reused), but on retry (after "address already in use") the params.append_range(image_args) reads freed memory, causing use-after-free that manifests as std::bad_alloc or broken_promise in non-sanitizer builds. Fix by taking docker_args and image_args by value so the coroutine frame owns the vectors for its entire lifetime. Fixes: https://scylladb.atlassian.net/browse/SCYLLADB-2003 Closes scylladb/scylladb#29932
81 lines
2.5 KiB
C++
81 lines
2.5 KiB
C++
/*
|
|
* Copyright (C) 2025-present ScyllaDB
|
|
*/
|
|
/*
|
|
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.1
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <filesystem>
|
|
#include <vector>
|
|
#include <variant>
|
|
#include <iosfwd>
|
|
|
|
#include <seastar/core/future.hh>
|
|
#include <seastar/core/iostream.hh>
|
|
#include <seastar/util/process.hh>
|
|
|
|
namespace tests::proc {
|
|
using namespace seastar;
|
|
|
|
std::filesystem::path find_file_in_path(std::string_view name,
|
|
const std::vector<std::filesystem::path>& path_prepend = {},
|
|
const std::vector<std::filesystem::path>& path_append = {}
|
|
);
|
|
|
|
class process_fixture {
|
|
class impl;
|
|
std::unique_ptr<impl> _impl;
|
|
|
|
process_fixture(std::unique_ptr<impl>);
|
|
public:
|
|
using buffer_type = temporary_buffer<char>;
|
|
using handler_result = consumption_result<char>;
|
|
using stream_handler = noncopyable_function<future<handler_result>(buffer_type)>;
|
|
using line_handler = noncopyable_function<future<handler_result>(std::string_view)>;
|
|
using handler_type = std::variant<std::monostate, stream_handler, line_handler>;
|
|
|
|
process_fixture(process_fixture&&) noexcept;
|
|
~process_fixture();
|
|
|
|
static future<process_fixture> create(const std::filesystem::path& exec
|
|
, const std::vector<std::string>& args
|
|
, const std::vector<std::string>& env = {}
|
|
, handler_type stdout_handler = {}
|
|
, handler_type stderr_handler = {}
|
|
, bool inherit_env = true
|
|
);
|
|
|
|
static line_handler create_copy_handler(std::ostream&);
|
|
|
|
using wait_exited = seastar::experimental::process::wait_exited;
|
|
using wait_signaled = seastar::experimental::process::wait_signaled;
|
|
using wait_status = seastar::experimental::process::wait_status;
|
|
|
|
future<wait_status> wait();
|
|
void terminate();
|
|
void kill();
|
|
|
|
input_stream<char> cout();
|
|
input_stream<char> cerr();
|
|
output_stream<char> cin();
|
|
};
|
|
|
|
enum class service_parse_state {
|
|
cont, success, failed
|
|
};
|
|
|
|
using parse_service_callback = std::function<service_parse_state(std::string_view)>;
|
|
|
|
future<std::tuple<process_fixture, int>> start_docker_service(
|
|
std::string_view name,
|
|
std::string_view image,
|
|
parse_service_callback stdout_parse = {},
|
|
parse_service_callback stderr_parse = {},
|
|
std::vector<std::string> docker_args = {},
|
|
std::vector<std::string> image_args = {},
|
|
int service_port = 0
|
|
);
|
|
}
|