From bf3e2e2b172dffbe745092a062f48bb6bc8b269f Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 13 Aug 2024 11:22:03 +0300 Subject: viewer-private#262 webrtc crashes on shutdown #2 --- indra/newview/llvoicewebrtc.cpp | 50 ++++++++++++++++++++++++++++++++--------- indra/newview/llvoicewebrtc.h | 6 +++-- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index ff3c0eccd2..1ee1e69b79 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -237,12 +237,27 @@ LLWebRTCVoiceClient::LLWebRTCVoiceClient() : //--------------------------------------------------- LLWebRTCVoiceClient::~LLWebRTCVoiceClient() +{ +} + +void LLWebRTCVoiceClient::cleanupSingleton() { if (mAvatarNameCacheConnection.connected()) { mAvatarNameCacheConnection.disconnect(); } + sShuttingDown = true; + if (mSession) + { + mSession->shutdownAllConnections(); + } + if (mNextSession) + { + mNextSession->shutdownAllConnections(); + } + cleanUp(); + sessionState::clearSessions(); } //--------------------------------------------------- @@ -656,6 +671,10 @@ void LLWebRTCVoiceClient::OnDevicesChanged(const llwebrtc::LLWebRTCVoiceDeviceLi void LLWebRTCVoiceClient::OnDevicesChangedImpl(const llwebrtc::LLWebRTCVoiceDeviceList &render_devices, const llwebrtc::LLWebRTCVoiceDeviceList &capture_devices) { + if (sShuttingDown) + { + return; + } LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE std::string inputDevice = gSavedSettings.getString("VoiceInputAudioDevice"); std::string outputDevice = gSavedSettings.getString("VoiceOutputAudioDevice"); @@ -1704,7 +1723,7 @@ void LLWebRTCVoiceClient::predSetUserMute(const LLWebRTCVoiceClient::sessionStat //------------------------------------------------------------------------ // Sessions -std::map LLWebRTCVoiceClient::sessionState::mSessions; +std::map LLWebRTCVoiceClient::sessionState::sSessions; LLWebRTCVoiceClient::sessionState::sessionState() : @@ -1791,13 +1810,19 @@ void LLWebRTCVoiceClient::sessionState::addSession( const std::string & channelID, LLWebRTCVoiceClient::sessionState::ptr_t& session) { - mSessions[channelID] = session; + sSessions[channelID] = session; } LLWebRTCVoiceClient::sessionState::~sessionState() { LL_DEBUGS("Voice") << "Destroying session CHANNEL=" << mChannelID << LL_ENDL; + if (!mShuttingDown) + { + shutdownAllConnections(); + } + mWebRTCConnections.clear(); + removeAllParticipants(); } @@ -1807,8 +1832,8 @@ LLWebRTCVoiceClient::sessionState::ptr_t LLWebRTCVoiceClient::sessionState::matc sessionStatePtr_t result; // *TODO: My kingdom for a lambda! - std::map::iterator it = mSessions.find(channel_id); - if (it != mSessions.end()) + std::map::iterator it = sSessions.find(channel_id); + if (it != sSessions.end()) { result = (*it).second; } @@ -1817,17 +1842,17 @@ LLWebRTCVoiceClient::sessionState::ptr_t LLWebRTCVoiceClient::sessionState::matc void LLWebRTCVoiceClient::sessionState::for_each(sessionFunc_t func) { - std::for_each(mSessions.begin(), mSessions.end(), boost::bind(for_eachPredicate, _1, func)); + std::for_each(sSessions.begin(), sSessions.end(), boost::bind(for_eachPredicate, _1, func)); } void LLWebRTCVoiceClient::sessionState::reapEmptySessions() { std::map::iterator iter; - for (iter = mSessions.begin(); iter != mSessions.end();) + for (iter = sSessions.begin(); iter != sSessions.end();) { if (iter->second->isEmpty()) { - iter = mSessions.erase(iter); + iter = sSessions.erase(iter); } else { @@ -1873,6 +1898,11 @@ LLWebRTCVoiceClient::sessionStatePtr_t LLWebRTCVoiceClient::addSession(const std } } +void LLWebRTCVoiceClient::sessionState::clearSessions() +{ + sSessions.clear(); +} + LLWebRTCVoiceClient::sessionStatePtr_t LLWebRTCVoiceClient::findP2PSession(const LLUUID &agent_id) { sessionStatePtr_t result = sessionState::matchSessionByChannelID(agent_id.asString()); @@ -1912,14 +1942,14 @@ void LLWebRTCVoiceClient::sessionState::processSessionStates() { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE - auto iter = mSessions.begin(); - while (iter != mSessions.end()) + auto iter = sSessions.begin(); + while (iter != sSessions.end()) { if (!iter->second->processConnectionStates() && iter->second->mShuttingDown) { // if the connections associated with a session are gone, // and this session is shutting down, remove it. - iter = mSessions.erase(iter); + iter = sSessions.erase(iter); } else { diff --git a/indra/newview/llvoicewebrtc.h b/indra/newview/llvoicewebrtc.h index f699bd6df9..48c50a1ea3 100644 --- a/indra/newview/llvoicewebrtc.h +++ b/indra/newview/llvoicewebrtc.h @@ -70,6 +70,7 @@ class LLWebRTCVoiceClient : public LLSingleton, virtual ~LLWebRTCVoiceClient(); public: + void cleanupSingleton() override; /// @name LLVoiceModuleInterface virtual implementations /// @see LLVoiceModuleInterface //@{ @@ -300,6 +301,7 @@ public: static void for_each(sessionFunc_t func); static void reapEmptySessions(); + static void clearSessions(); bool isEmpty() { return mWebRTCConnections.empty(); } @@ -319,7 +321,7 @@ public: participantUUIDMap mParticipantsByUUID; static bool hasSession(const std::string &sessionID) - { return mSessions.find(sessionID) != mSessions.end(); } + { return sSessions.find(sessionID) != sSessions.end(); } bool mHangupOnLastLeave; // notify observers after the session becomes empty. bool mNotifyOnFirstJoin; // notify observers when the first peer joins. @@ -330,7 +332,7 @@ public: private: - static std::map mSessions; // canonical list of outstanding sessions. + static std::map sSessions; // canonical list of outstanding sessions. static void for_eachPredicate(const std::pair &a, -- cgit v1.2.3