diff --git a/webrtc/p2p/base/turnserver.cc b/webrtc/p2p/base/turnserver.cc index 7dd9e19f63..3a574673c3 100644 --- a/webrtc/p2p/base/turnserver.cc +++ b/webrtc/p2p/base/turnserver.cc @@ -16,6 +16,7 @@ #include "webrtc/p2p/base/common.h" #include "webrtc/p2p/base/packetsocketfactory.h" #include "webrtc/p2p/base/stun.h" +#include "webrtc/base/bind.h" #include "webrtc/base/bytebuffer.h" #include "webrtc/base/helpers.h" #include "webrtc/base/logging.h" @@ -525,13 +526,21 @@ void TurnServer::DestroyInternalSocket(rtc::AsyncPacketSocket* socket) { InternalSocketMap::iterator iter = server_sockets_.find(socket); if (iter != server_sockets_.end()) { rtc::AsyncPacketSocket* socket = iter->first; - // We must destroy the socket async to avoid invalidating the sigslot - // callback list iterator inside a sigslot callback. - rtc::Thread::Current()->Dispose(socket); server_sockets_.erase(iter); + // We must destroy the socket async to avoid invalidating the sigslot + // callback list iterator inside a sigslot callback. (In other words, + // deleting an object from within a callback from that object). + sockets_to_delete_.push_back( + std::unique_ptr(socket)); + invoker_.AsyncInvoke(RTC_FROM_HERE, rtc::Thread::Current(), + rtc::Bind(&TurnServer::FreeSockets, this)); } } +void TurnServer::FreeSockets() { + sockets_to_delete_.clear(); +} + TurnServerConnection::TurnServerConnection(const rtc::SocketAddress& src, ProtocolType proto, rtc::AsyncPacketSocket* socket) diff --git a/webrtc/p2p/base/turnserver.h b/webrtc/p2p/base/turnserver.h index 09b553ef17..608e0434e4 100644 --- a/webrtc/p2p/base/turnserver.h +++ b/webrtc/p2p/base/turnserver.h @@ -16,8 +16,10 @@ #include #include #include +#include #include "webrtc/p2p/base/portinterface.h" +#include "webrtc/base/asyncinvoker.h" #include "webrtc/base/asyncpacketsocket.h" #include "webrtc/base/messagequeue.h" #include "webrtc/base/sigslot.h" @@ -258,6 +260,9 @@ class TurnServer : public sigslot::has_slots<> { void OnAllocationDestroyed(TurnServerAllocation* allocation); void DestroyInternalSocket(rtc::AsyncPacketSocket* socket); + // Just clears |sockets_to_delete_|; called asynchronously. + void FreeSockets(); + typedef std::map InternalSocketMap; typedef std::map { InternalSocketMap server_sockets_; ServerSocketMap server_listen_sockets_; + // Used when we need to delete a socket asynchronously. + std::vector> sockets_to_delete_; std::unique_ptr external_socket_factory_; rtc::SocketAddress external_addr_; AllocationMap allocations_; + rtc::AsyncInvoker invoker_; + // For testing only. If this is non-zero, the next NONCE will be generated // from this value, and it will be reset to 0 after generating the NONCE. int64_t ts_for_next_nonce_ = 0;