mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-29 11:10:40 +00:00
test: kmip: Fix segfault from premature destruction of port_promise
`kmip_test_helper()` is a utility function to spawn a dedicated PyKMIP
server for a particular Boost test case. The function runs the server as
an external process and uses a thread to parse the port from the
server's logs. The thread communicates the port to the main thread via
a promise.
The current implementation has a bug where the thread may set a value
to the promise after its destruction, causing a segfault. This happens
when the server does not start within 20 seconds, in which case the port
future throws and the stack unwinding machinery destroys the port
promise before the thread that writes to it.
Fix the bug by declaring the promise before the cleanup action.
The bug has been encountered in CI runs on slow machines, where the
PyKMIP server takes too long to create its internal tables (due to slow
fdatasync calls from SQLite). This patch does not improve CI stability -
it only ensures that the error condition is properly reflected in the
test output.
This patch is not a backport. The same bug has been fixed in master as
part of a larger rewrite of the `kmip_test_helper()` (see 722e2bce96).
Refs #24747, #24842.
Fixes #24574.
Signed-off-by: Nikos Dragazis <nikolaos.dragazis@scylladb.com>
Closes scylladb/scylladb#25029
This commit is contained in:
committed by
Pavel Emelyanov
parent
be94db3ace
commit
5ae00a3dab
@@ -305,6 +305,9 @@ static future<> kmip_test_helper(const std::function<future<>(const kmip_test_in
|
||||
|
||||
std::future<void> pykmip_status;
|
||||
|
||||
std::promise<int> port_promise;
|
||||
auto fut = port_promise.get_future();
|
||||
|
||||
static const char* def_resourcedir = "./test/resource/certs";
|
||||
const char* resourcedir = std::getenv("KMIP_RESOURCE_DIR");
|
||||
if (resourcedir == nullptr) {
|
||||
@@ -368,9 +371,6 @@ database_path=:memory:
|
||||
bp::env["TMPDIR"]=tmp.path().string()
|
||||
);
|
||||
|
||||
std::promise<int> port_promise;
|
||||
auto f = port_promise.get_future();
|
||||
|
||||
pykmip_status = std::async([&] {
|
||||
static std::regex port_ex("Listening on (\\d+)");
|
||||
|
||||
@@ -393,10 +393,10 @@ database_path=:memory:
|
||||
}
|
||||
});
|
||||
// arbitrary timeout of 20s for the server to make some output. Very generous.
|
||||
if (f.wait_for(20s) == std::future_status::timeout) {
|
||||
if (fut.wait_for(20s) == std::future_status::timeout) {
|
||||
throw std::runtime_error("Could not start pykmip");
|
||||
}
|
||||
auto port = f.get();
|
||||
auto port = fut.get();
|
||||
if (port <= 0) {
|
||||
throw std::runtime_error("Invalid port");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user