Skip to content
Snippets Groups Projects
Commit 0b1b9ee7 authored by Sébastien Blin's avatar Sébastien Blin
Browse files

turn_cache: avoid potential deadlock on start

Creating the TURNTransport and starting it can call the callback
in the same thread, causing a deadlock. This patch retriggers the
callback to avoid a double lock.

Change-Id: I955ce0503a7f34c0d2241000193861f9b5d1cb49
parent 5a30c3b8
No related branches found
No related tags found
No related merge requests found
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "fileutils.h" #include "fileutils.h"
#include "manager.h" #include "manager.h"
#include "opendht/thread_pool.h" // TODO remove asio #include "opendht/thread_pool.h" // TODO remove asio
#include "turn_cache.h"
namespace jami { namespace jami {
...@@ -37,10 +38,25 @@ TurnCache::TurnCache(const std::string& accountId, ...@@ -37,10 +38,25 @@ TurnCache::TurnCache(const std::string& accountId,
{ {
refreshTimer_ = std::make_unique<asio::steady_timer>(*io_context, refreshTimer_ = std::make_unique<asio::steady_timer>(*io_context,
std::chrono::steady_clock::now()); std::chrono::steady_clock::now());
onConnectedTimer_ = std::make_unique<asio::steady_timer>(*io_context,
std::chrono::steady_clock::now());
reconfigure(params, enabled); reconfigure(params, enabled);
} }
TurnCache::~TurnCache() {} TurnCache::~TurnCache() {
{
std::lock_guard<std::mutex> lock(shutdownMtx_);
onConnectedTimer_->cancel();
onConnectedTimer_.reset();
}
{
std::lock_guard<std::mutex> lock(cachedTurnMutex_);
testTurnV4_.reset();
testTurnV6_.reset();
cacheTurnV4_.reset();
cacheTurnV6_.reset();
}
}
std::optional<IpAddr> std::optional<IpAddr>
TurnCache::getResolvedTurn(uint16_t family) const TurnCache::getResolvedTurn(uint16_t family) const
...@@ -159,6 +175,25 @@ TurnCache::testTurn(IpAddr server) ...@@ -159,6 +175,25 @@ TurnCache::testTurn(IpAddr server)
try { try {
turn = std::make_unique<TurnTransport>( turn = std::make_unique<TurnTransport>(
params, std::move([this, server](bool ok) { params, std::move([this, server](bool ok) {
// Stop server in an async job, because this callback can be called
// immediately and cachedTurnMutex_ must not be locked.
std::lock_guard<std::mutex> lock(shutdownMtx_);
if (onConnectedTimer_) {
onConnectedTimer_->expires_at(std::chrono::steady_clock::now());
onConnectedTimer_->async_wait(std::bind(&TurnCache::onConnected, this, std::placeholders::_1, ok, server));
}
}));
} catch (const std::exception& e) {
JAMI_ERROR("TurnTransport creation error: {}", e.what());
}
}
void
TurnCache::onConnected(const asio::error_code& ec, bool ok, IpAddr server)
{
if (ec == asio::error::operation_aborted)
return;
std::lock_guard<std::mutex> lk(cachedTurnMutex_); std::lock_guard<std::mutex> lk(cachedTurnMutex_);
auto& cacheTurn = server.isIpv4() ? cacheTurnV4_ : cacheTurnV6_; auto& cacheTurn = server.isIpv4() ? cacheTurnV4_ : cacheTurnV6_;
if (!ok) { if (!ok) {
...@@ -169,14 +204,11 @@ TurnCache::testTurn(IpAddr server) ...@@ -169,14 +204,11 @@ TurnCache::testTurn(IpAddr server)
cacheTurn = std::make_unique<IpAddr>(server); cacheTurn = std::make_unique<IpAddr>(server);
} }
refreshTurnDelay(!cacheTurnV6_ && !cacheTurnV4_); refreshTurnDelay(!cacheTurnV6_ && !cacheTurnV4_);
auto& turn = server.isIpv4() ? testTurnV4_ : testTurnV6_; if (auto& turn = server.isIpv4() ? testTurnV4_ : testTurnV6_)
turn->shutdown(); turn->shutdown();
}));
} catch (const std::exception& e) {
JAMI_ERROR("TurnTransport creation error: {}", e.what());
}
} }
void void
TurnCache::refreshTurnDelay(bool scheduleNext) TurnCache::refreshTurnDelay(bool scheduleNext)
{ {
......
...@@ -80,9 +80,15 @@ private: ...@@ -80,9 +80,15 @@ private:
std::unique_ptr<IpAddr> cacheTurnV4_ {}; std::unique_ptr<IpAddr> cacheTurnV4_ {};
std::unique_ptr<IpAddr> cacheTurnV6_ {}; std::unique_ptr<IpAddr> cacheTurnV6_ {};
void onConnected(const asio::error_code& ec, bool ok, IpAddr server);
// io // io
std::shared_ptr<asio::io_context> io_context; std::shared_ptr<asio::io_context> io_context;
std::unique_ptr<asio::steady_timer> refreshTimer_; std::unique_ptr<asio::steady_timer> refreshTimer_;
std::unique_ptr<asio::steady_timer> onConnectedTimer_;
std::mutex shutdownMtx_;
}; };
} // namespace jami } // namespace jami
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment