Skip to content

Commit 1194bf5

Browse files
committed
Fixed race condition crash on Async Queries with bound values
1 parent 61b76a7 commit 1194bf5

4 files changed

Lines changed: 34 additions & 16 deletions

File tree

mariadbpp

src/connection.cpp

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,27 +81,47 @@ bool Connection::throwQueryError(game_state& gs, mariadb::connection_ref connect
8181
GameDataDBAsyncResult* Connection::pushAsyncQuery(game_state& gs, mariadb::connection_ref connection, auto_array<game_value> boundValues, r_string queryString) {
8282
auto gd_res = new GameDataDBAsyncResult();
8383
gd_res->data = std::make_shared<GameDataDBAsyncResult::dataT>();
84+
85+
86+
//If we give them to task, it will destruct the array after task is done, and may call dealloc int he pool allocator
87+
std::vector<
88+
std::variant<float, bool, r_string>
89+
> boundValuesQuery;
90+
91+
for (auto& it : boundValues) {
92+
switch (it.type_enum()) {
93+
case game_data_type::SCALAR: boundValuesQuery.emplace_back(static_cast<float>(it)); break;
94+
case game_data_type::BOOL: boundValuesQuery.emplace_back(static_cast<bool>(it)); break;
95+
case game_data_type::STRING: boundValuesQuery.emplace_back(static_cast<r_string>(it)); break;
96+
default:;
97+
}
98+
}
99+
84100
gd_res->data->fut = Threading::get().pushTask(connection,
85-
[queryString, boundValues, result = gd_res->data, &gs](mariadb::connection_ref con) -> bool {
101+
[queryString, boundValuesQuery, result = gd_res->data, &gs](mariadb::connection_ref con) -> bool {
86102
try {
87103
auto statement = con->create_statement(queryString);
88104

89-
if (statement->get_bind_count() != boundValues.size()) {
105+
if (statement->get_bind_count() != boundValuesQuery.size()) {
90106
invoker_lock l;
91107
throwQueryError(gs, con, 2,
92-
r_string("Invalid number of bind values. Expected "sv)+std::to_string(statement->get_bind_count())+" got "sv+std::to_string(boundValues.size())
108+
r_string("Invalid number of bind values. Expected "sv)+std::to_string(statement->get_bind_count())+" got "sv+std::to_string(boundValuesQuery.size())
93109
, queryString);
94110
return false;
95111
}
96112
uint32_t idx = 0;
97-
for (auto& it : boundValues) {
98-
99-
switch (it.type_enum()) {
100-
case game_data_type::SCALAR: statement->set_float(idx++, static_cast<float>(it)); break;
101-
case game_data_type::BOOL: statement->set_boolean(idx++, static_cast<bool>(it)); break;
102-
case game_data_type::STRING: statement->set_string(idx++, static_cast<r_string>(it)); break;
103-
default:;
104-
}
113+
for (auto& it : boundValuesQuery) {
114+
std::visit([&idx, &statement](auto && arg) {
115+
using T = std::decay_t<decltype(arg)>;
116+
if constexpr (std::is_same_v<T, float>)
117+
statement->set_float(idx++, arg);
118+
else if constexpr (std::is_same_v<T, bool>)
119+
statement->set_boolean(idx++, arg);
120+
else if constexpr (std::is_same_v<T, r_string>)
121+
statement->set_string(idx++, arg);
122+
else
123+
static_assert(false, "non-exhaustive visitor!");
124+
}, it);
105125
}
106126
result->res = statement->query();
107127
return true;
@@ -229,7 +249,6 @@ game_value Connection::cmd_execute(game_state& gs, game_value_parameter con, gam
229249

230250
uint32_t idx = 0;
231251
for (auto& it : query->boundValues) {
232-
233252
switch (it.type_enum()) {
234253
case game_data_type::SCALAR: statement->set_float(idx++, static_cast<float>(it)); break;
235254
case game_data_type::BOOL: statement->set_boolean(idx++, static_cast<bool>(it)); break;
@@ -274,7 +293,6 @@ game_value Connection::cmd_executeAsync(game_state& gs, game_value_parameter con
274293
auto session = con.get_as<GameDataDBConnection>()->session;
275294
auto query = qu.get_as<GameDataDBQuery>();
276295

277-
278296
auto gd_res = pushAsyncQuery(gs, session, query->boundValues, query->getQueryString());
279297
Threading::get().pushAsyncWork(gd_res);
280298
__itt_task_end(domainConnection);

src/res.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ game_value Result::cmd_toArray(game_state&, game_value_parameter right) {
3838
while (res->next()) {
3939
auto_array<game_value> row;
4040

41-
for (size_t i = 0u; i < res->column_count(); ++i) {
41+
for (mariadb::u32 i = 0u; i < res->column_count(); ++i) {
4242
switch (res->column_type(i)) {
4343
case mariadb::value::null: row.emplace_back(game_value{}); break;
4444
case mariadb::value::date: row.emplace_back(res->get_date(i).str()); break;

0 commit comments

Comments
 (0)