Merge pull request #1850 from secondlife/roxie/webrtc-voice-crash-fixes

Various crash fixes.  ALso fixes an issue with adhoc/group calls on vivox regions.
meow-7.2.2
Roxanne Skelly 2024-06-26 15:46:07 -07:00 committed by GitHub
commit 9bc3dfbdea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 75 additions and 30 deletions

View File

@ -357,22 +357,20 @@ void LLConversationItemSession::clearParticipants()
void LLConversationItemSession::clearAndDeparentModels()
{
std::for_each(mChildren.begin(), mChildren.end(),
[](LLFolderViewModelItem* c)
for (LLFolderViewModelItem* child : mChildren)
{
if (child->getNumRefs() == 0)
{
if (c->getNumRefs() == 0)
{
// LLConversationItemParticipant can be created but not assigned to any view,
// it was waiting for an "add_participant" event to be processed
delete c;
}
else
{
// Model is still assigned to some view/widget
c->setParent(NULL);
}
// LLConversationItemParticipant can be created but not assigned to any view,
// it was waiting for an "add_participant" event to be processed
delete child;
}
);
else
{
// Model is still assigned to some view/widget
child->setParent(NULL);
}
}
mChildren.clear();
}

View File

@ -102,6 +102,26 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id)
LLFloaterIMSessionTab::~LLFloaterIMSessionTab()
{
delete mRefreshTimer;
LLFloaterIMContainer* im_container = LLFloaterIMContainer::findInstance();
if (im_container)
{
LLParticipantList* session = dynamic_cast<LLParticipantList*>(im_container->getSessionModel(mSessionID));
if (session)
{
for (const conversations_widgets_map::value_type& widget_pair : mConversationsWidgets)
{
LLFolderViewItem* widget = widget_pair.second;
LLFolderViewModelItem* item_vmi = widget->getViewModelItem();
if (item_vmi && item_vmi->getNumRefs() == 1)
{
// This is the last pointer, remove participant from session
// before participant gets deleted on destroyView.
session->removeChild(item_vmi);
}
}
}
}
}
// static
@ -663,6 +683,27 @@ void LLFloaterIMSessionTab::removeConversationViewParticipant(const LLUUID& part
LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id);
if (widget)
{
LLFolderViewModelItem* item_vmi = widget->getViewModelItem();
if (item_vmi && item_vmi->getNumRefs() == 1)
{
// This is the last pointer, remove participant from session
// before participant gets deleted on destroyView.
//
// Floater (widget) and participant's view can simultaneously
// co-own the model, in which case view is responsible for
// the deletion and floater is free to clear and recreate
// the list, yet there are cases where only widget owns
// the pointer so it should do the cleanup.
// See "add_participant".
//
// Todo: If it keeps causing issues turn participants
// into LLPointers in the session
LLParticipantList* session = getParticipantList();
if (session)
{
session->removeChild(item_vmi);
}
}
widget->destroyView();
}
mConversationsWidgets.erase(participant_id);

View File

@ -3413,11 +3413,11 @@ LLUUID LLIMMgr::addSession(
((IM_NOTHING_SPECIAL == dialog) || (IM_SESSION_P2P_INVITE == dialog) || (IM_SESSION_CONFERENCE_START == dialog)) &&
ids.size())
{
LLIMModel::LLIMSession* ad_hoc_found = LLIMModel::getInstance()->findAdHocIMSession(ids);
if (ad_hoc_found)
session = LLIMModel::getInstance()->findAdHocIMSession(ids);
if (session)
{
new_session = false;
session_id = ad_hoc_found->mSessionID;
session_id = session->mSessionID;
}
}
@ -3853,7 +3853,7 @@ bool LLIMMgr::startCall(const LLUUID& session_id, LLVoiceChannel::EDirection dir
{
LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id);
if (!voice_channel) return false;
if (!voice_channel_info.isUndefined())
if (voice_channel_info.isDefined() && voice_channel_info.isMap() && voice_channel_info.size() > 0)
{
voice_channel->setChannelInfo(voice_channel_info);
}

View File

@ -96,7 +96,7 @@ void LLVoiceChannel::setChannelInfo(const LLSD &channelInfo)
if (mState == STATE_NO_CHANNEL_INFO)
{
if (mChannelInfo.isUndefined())
if (mChannelInfo.isUndefined() || !mChannelInfo.isMap() || mChannelInfo.size() == 0)
{
LLNotificationsUtil::add("VoiceChannelJoinFailed", mNotifyArgs);
LL_WARNS("Voice") << "Received empty channel info for channel " << mSessionName << LL_ENDL;
@ -122,7 +122,7 @@ void LLVoiceChannel::onChange(EStatusType type, const LLSD& channelInfo, bool pr
{
LL_DEBUGS("Voice") << "Incoming channel info: " << channelInfo << LL_ENDL;
LL_DEBUGS("Voice") << "Current channel info: " << mChannelInfo << LL_ENDL;
if (mChannelInfo.isUndefined())
if (mChannelInfo.isUndefined() || (mChannelInfo.isMap() && mChannelInfo.size() == 0))
{
mChannelInfo = channelInfo;
}
@ -477,7 +477,7 @@ void LLVoiceChannelGroup::setChannelInfo(const LLSD& channelInfo)
if (mState == STATE_NO_CHANNEL_INFO)
{
if(!mChannelInfo.isUndefined())
if(mChannelInfo.isDefined() && mChannelInfo.isMap())
{
setState(STATE_READY);
@ -676,9 +676,9 @@ void LLVoiceChannelProximal::activate()
// we're connected to a non-spatial channel, so disconnect.
LLVoiceClient::getInstance()->leaveNonSpatialChannel();
}
LLVoiceClient::getInstance()->activateSpatialChannel(true);
LLVoiceChannel::activate();
}
void LLVoiceChannelProximal::onChange(EStatusType type, const LLSD& channelInfo, bool proximal)
@ -751,7 +751,7 @@ void LLVoiceChannelProximal::deactivate()
{
setState(STATE_HUNG_UP);
}
LLVoiceClient::getInstance()->removeObserver(this);
LLVoiceClient::getInstance()->activateSpatialChannel(false);
}
@ -907,7 +907,7 @@ void LLVoiceChannelP2P::setChannelInfo(const LLSD& channel_info)
}
mReceivedCall = TRUE;
if (!channel_info.isUndefined())
if (channel_info.isDefined() && channel_info.isMap())
{
mIncomingCallInterface = LLVoiceClient::getInstance()->getIncomingCallInterface(channel_info);
}

View File

@ -5105,25 +5105,31 @@ void LLVivoxVoiceClient::processChannels(bool process)
bool LLVivoxVoiceClient::isCurrentChannel(const LLSD &channelInfo)
{
if (!mProcessChannels || (channelInfo["voice_server_type"].asString() != VIVOX_VOICE_SERVER_TYPE))
if (!mProcessChannels || (channelInfo.has("voice_server_type") && channelInfo["voice_server_type"].asString() != VIVOX_VOICE_SERVER_TYPE))
{
return false;
}
if (mAudioSession)
// favor the next audio session, as that's the one we're bringing up.
sessionStatePtr_t session = mNextAudioSession;
if (!session)
{
session = mAudioSession;
}
if (session)
{
if (!channelInfo["session_handle"].asString().empty())
{
return mAudioSession->mHandle == channelInfo["session_handle"].asString();
return session->mHandle == channelInfo["session_handle"].asString();
}
return channelInfo["channel_uri"].asString() == mAudioSession->mSIPURI;
return channelInfo["channel_uri"].asString() == session->mSIPURI;
}
return false;
}
bool LLVivoxVoiceClient::compareChannels(const LLSD& channelInfo1, const LLSD& channelInfo2)
{
return (channelInfo1["voice_server_type"] == VIVOX_VOICE_SERVER_TYPE) &&
(channelInfo1["voice_server_type"] == channelInfo2["voice_server_type"]) &&
return (!channelInfo1.has("voice_server_type") || (channelInfo1["voice_server_type"] == VIVOX_VOICE_SERVER_TYPE)) &&
(!channelInfo2.has("voice_server_type") || (channelInfo2["voice_server_type"] == VIVOX_VOICE_SERVER_TYPE)) &&
(channelInfo1["channel_uri"] == channelInfo2["channel_uri"]);
}