From ec3462fabeea3fb3a26720c23098f9400c1c6e54 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 3 Oct 2014 10:35:11 -0400 Subject: [PATCH] fixed race condition --- TunnelPool.cpp | 43 ++++++++++++++++++++++++++++++++----------- TunnelPool.h | 9 ++++++--- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/TunnelPool.cpp b/TunnelPool.cpp index 3aef8120..4b7882d8 100644 --- a/TunnelPool.cpp +++ b/TunnelPool.cpp @@ -25,7 +25,10 @@ namespace tunnel void TunnelPool::TunnelCreated (InboundTunnel * createdTunnel) { - m_InboundTunnels.insert (createdTunnel); + { + std::unique_lock l(m_InboundTunnelsMutex); + m_InboundTunnels.insert (createdTunnel); + } m_LocalDestination.SetLeaseSetUpdated (); } @@ -34,15 +37,18 @@ namespace tunnel if (expiredTunnel) { expiredTunnel->SetTunnelPool (nullptr); - m_InboundTunnels.erase (expiredTunnel); for (auto it: m_Tests) if (it.second.second == expiredTunnel) it.second.second = nullptr; RecreateInboundTunnel (expiredTunnel); + + std::unique_lock l(m_InboundTunnelsMutex); + m_InboundTunnels.erase (expiredTunnel); } } void TunnelPool::TunnelCreated (OutboundTunnel * createdTunnel) { + std::unique_lock l(m_OutboundTunnelsMutex); m_OutboundTunnels.insert (createdTunnel); } @@ -51,10 +57,12 @@ namespace tunnel if (expiredTunnel) { expiredTunnel->SetTunnelPool (nullptr); - m_OutboundTunnels.erase (expiredTunnel); for (auto it: m_Tests) if (it.second.first == expiredTunnel) it.second.first = nullptr; RecreateOutboundTunnel (expiredTunnel); + + std::unique_lock l(m_OutboundTunnelsMutex); + m_OutboundTunnels.erase (expiredTunnel); } } @@ -62,6 +70,7 @@ namespace tunnel { std::vector v; int i = 0; + std::unique_lock l(m_InboundTunnelsMutex); for (auto it : m_InboundTunnels) { if (i >= num) break; @@ -74,19 +83,21 @@ namespace tunnel return v; } - OutboundTunnel * TunnelPool::GetNextOutboundTunnel (OutboundTunnel * suggested) + OutboundTunnel * TunnelPool::GetNextOutboundTunnel (OutboundTunnel * suggested) const { + std::unique_lock l(m_OutboundTunnelsMutex); return GetNextTunnel (m_OutboundTunnels, suggested); } - InboundTunnel * TunnelPool::GetNextInboundTunnel (InboundTunnel * suggested) + InboundTunnel * TunnelPool::GetNextInboundTunnel (InboundTunnel * suggested) const { + std::unique_lock l(m_InboundTunnelsMutex); return GetNextTunnel (m_InboundTunnels, suggested); } template typename TTunnels::value_type TunnelPool::GetNextTunnel (TTunnels& tunnels, - typename TTunnels::value_type suggested) + typename TTunnels::value_type suggested) const { if (tunnels.empty ()) return nullptr; if (suggested && tunnels.count (suggested) > 0 && suggested->IsEstablished ()) @@ -110,14 +121,20 @@ namespace tunnel void TunnelPool::CreateTunnels () { int num = 0; - for (auto it : m_InboundTunnels) - if (it->IsEstablished ()) num++; + { + std::unique_lock l(m_InboundTunnelsMutex); + for (auto it : m_InboundTunnels) + if (it->IsEstablished ()) num++; + } for (int i = num; i < m_NumTunnels; i++) CreateInboundTunnel (); num = 0; - for (auto it : m_OutboundTunnels) - if (it->IsEstablished ()) num++; + { + std::unique_lock l(m_OutboundTunnelsMutex); + for (auto it : m_OutboundTunnels) + if (it->IsEstablished ()) num++; + } for (int i = num; i < m_NumTunnels; i++) CreateOutboundTunnel (); } @@ -134,6 +151,7 @@ namespace tunnel if (it.second.first->GetState () == eTunnelStateTestFailed) { it.second.first->SetState (eTunnelStateFailed); + std::unique_lock l(m_OutboundTunnelsMutex); m_OutboundTunnels.erase (it.second.first); } else @@ -144,7 +162,10 @@ namespace tunnel if (it.second.second->GetState () == eTunnelStateTestFailed) { it.second.second->SetState (eTunnelStateFailed); - m_InboundTunnels.erase (it.second.second); + { + std::unique_lock l(m_InboundTunnelsMutex); + m_InboundTunnels.erase (it.second.second); + } m_LocalDestination.SetLeaseSetUpdated (); } else diff --git a/TunnelPool.h b/TunnelPool.h index e0ced205..c08d5ece 100644 --- a/TunnelPool.h +++ b/TunnelPool.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "Identity.h" #include "LeaseSet.h" #include "RouterInfo.h" @@ -38,8 +39,8 @@ namespace tunnel void TunnelCreated (OutboundTunnel * createdTunnel); void TunnelExpired (OutboundTunnel * expiredTunnel); std::vector GetInboundTunnels (int num) const; - OutboundTunnel * GetNextOutboundTunnel (OutboundTunnel * suggested = nullptr); - InboundTunnel * GetNextInboundTunnel (InboundTunnel * suggested = nullptr); + OutboundTunnel * GetNextOutboundTunnel (OutboundTunnel * suggested = nullptr) const; + InboundTunnel * GetNextInboundTunnel (InboundTunnel * suggested = nullptr) const; const i2p::data::IdentHash& GetIdentHash () const { return m_LocalDestination.GetIdentHash (); }; void TestTunnels (); @@ -53,14 +54,16 @@ namespace tunnel void RecreateOutboundTunnel (OutboundTunnel * tunnel); template typename TTunnels::value_type GetNextTunnel (TTunnels& tunnels, - typename TTunnels::value_type suggested = nullptr); + typename TTunnels::value_type suggested = nullptr) const; const i2p::data::RouterInfo * SelectNextHop (const i2p::data::RouterInfo * prevHop) const; private: i2p::data::LocalDestination& m_LocalDestination; int m_NumHops, m_NumTunnels; + mutable std::mutex m_InboundTunnelsMutex; std::set m_InboundTunnels; // recent tunnel appears first + mutable std::mutex m_OutboundTunnelsMutex; std::set m_OutboundTunnels; std::map > m_Tests;