fix: Data race in new webserver (#1926)

There was a data race inside `CoroutineGroup` because internal timer was
used from multiple threads in the methods `asyncWait()` and
`onCoroutineComplete()`. Changing `registerForeign()` to spawn to the
same `yield_context` fixes the problem because now the timer is accessed
only from the same coroutine which has an internal strand.

During debugging I also added websocket support for `request_gun` tool.
This commit is contained in:
Sergey Kuznetsov
2025-02-27 15:08:46 +00:00
committed by GitHub
parent b909b8879d
commit d11e7bc60e
13 changed files with 116 additions and 32 deletions

View File

@@ -56,13 +56,15 @@ CoroutineGroup::spawn(boost::asio::yield_context yield, std::function<void(boost
}
std::optional<std::function<void()>>
CoroutineGroup::registerForeign()
CoroutineGroup::registerForeign(boost::asio::yield_context yield)
{
if (isFull())
return std::nullopt;
++childrenCounter_;
return [this]() { onCoroutineCompleted(); };
// It is important to spawn onCoroutineCompleted() to the same coroutine as will be calling asyncWait().
// timer_ here is not thread safe, so without spawn there could be a data race.
return [this, yield]() { boost::asio::spawn(yield, [this](auto&&) { onCoroutineCompleted(); }); };
}
void