From e44450cce1cd3a9077aec5514a1b9e65b8cffa0a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 6 May 2014 19:53:35 +0100 Subject: Revert "fix infinite recursion loop in SendGridInstantMessageViaXMLRPCAsync()" There is a problem here with infinite recursion, but this patch loses the 'hunting' behaviour where the code will attempt multiple lookups if the avatar is teleporting rapidly around different simulators. This patch only does a single lookup before giving up. This reverts commit cecb446e0e91ede0b05ea9cf40c1313782241f3d. --- .../Avatar/InstantMessage/MessageTransferModule.cs | 178 ++++++++++++--------- 1 file changed, 99 insertions(+), 79 deletions(-) (limited to 'OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs') diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index 4f8e2cd..40a400f 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -428,7 +428,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage /// /// delegate for sending a grid instant message asynchronously /// - public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result); + public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID); protected virtual void GridInstantMessageCompleted(IAsyncResult iar) { @@ -442,118 +442,138 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage { GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; - d.BeginInvoke(im, result, GridInstantMessageCompleted, d); + d.BeginInvoke(im, result, UUID.Zero, GridInstantMessageCompleted, d); } /// - /// Internal SendGridInstantMessage over XMLRPC method. + /// Recursive SendGridInstantMessage over XMLRPC method. /// This is called from within a dedicated thread. + /// The first time this is called, prevRegionHandle will be 0 Subsequent times this is called from + /// itself, prevRegionHandle will be the last region handle that we tried to send. + /// If the handles are the same, we look up the user's location using the grid. + /// If the handles are still the same, we end. The send failed. /// - private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result) + /// + /// Pass in 0 the first time this method is called. It will be called recursively with the last + /// regionhandle tried + /// + protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID) { UUID toAgentID = new UUID(im.toAgentID); - UUID regionID; - bool lookupAgent; - /* - * Try to get what region the agent is in from the cache. - */ + PresenceInfo upd = null; + + bool lookupAgent = false; + lock (m_UserRegionMap) { - lookupAgent = !m_UserRegionMap.TryGetValue(toAgentID, out regionID); + if (m_UserRegionMap.ContainsKey(toAgentID)) + { + upd = new PresenceInfo(); + upd.RegionID = m_UserRegionMap[toAgentID]; + + // We need to compare the current regionhandle with the previous region handle + // or the recursive loop will never end because it will never try to lookup the agent again + if (prevRegionID == upd.RegionID) + { + lookupAgent = true; + } + } + else + { + lookupAgent = true; + } } + - while (true) + // Are we needing to look-up an agent? + if (lookupAgent) { - - /* - * If not in cache, try to find out what region the agent is in. - * Also do this if we know the existing cache entry is bad. - */ - if (lookupAgent) + // Non-cached user agent lookup. + PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); + if (presences != null && presences.Length > 0) { - PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); - - regionID = UUID.Zero; - if (presences != null) + foreach (PresenceInfo p in presences) { - foreach (PresenceInfo p in presences) + if (p.RegionID != UUID.Zero) { - if (p.RegionID != UUID.Zero) - { - regionID = p.RegionID; - break; - } + upd = p; + break; } } + } - // If not found, message is undeliverable - if (regionID == UUID.Zero) + if (upd != null) + { + // check if we've tried this before.. + // This is one way to end the recursive loop + // + if (upd.RegionID == prevRegionID) { - break; + // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); + HandleUndeliveredMessage(im, result); + return; } } - - /* - * Try to find out about region. - * If unable, message is undeliverable. - */ - GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, regionID); - if (reginfo == null) + else { - m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", regionID); - break; + // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); + HandleUndeliveredMessage(im, result); + return; } + } - /* - * Try to send message to agent in the region. - */ - Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); - msgdata["region_handle"] = 0; - bool imresult = doIMSending(reginfo, msgdata); - - /* - * If message delivery successful, save cache entry because we know it is good. - * Then tell caller message has been delivered and we are done. - */ - if (imresult) + if (upd != null) + { + GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, + upd.RegionID); + if (reginfo != null) { - lock (m_UserRegionMap) + Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); + // Not actually used anymore, left in for compatibility + // Remove at next interface change + // + msgdata["region_handle"] = 0; + bool imresult = doIMSending(reginfo, msgdata); + if (imresult) + { + // IM delivery successful, so store the Agent's location in our local cache. + lock (m_UserRegionMap) + { + if (m_UserRegionMap.ContainsKey(toAgentID)) + { + m_UserRegionMap[toAgentID] = upd.RegionID; + } + else + { + m_UserRegionMap.Add(toAgentID, upd.RegionID); + } + } + result(true); + } + else { - m_UserRegionMap[toAgentID] = regionID; + // try again, but lookup user this time. + // Warning, this must call the Async version + // of this method or we'll be making thousands of threads + // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync + // The version that spawns the thread is SendGridInstantMessageViaXMLRPC + + // This is recursive!!!!! + SendGridInstantMessageViaXMLRPCAsync(im, result, + upd.RegionID); } - result(true); - return; } - - /* - * Message delivery failed. - * If we just looked up what region the agent is in, message is undeliverable. - */ - if (lookupAgent) + else { - break; + m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID); + HandleUndeliveredMessage(im, result); } - - /* - * We used a cached entry that we now know is bad. - * Try again by searching the grid for the user. - */ - lookupAgent = true; } - - /* - * Message is undeliverable for one reason or another. - * Remove possible bad entry from cache. - * Then inform caller that the message is undeliverable. - */ - lock (m_UserRegionMap) + else { - m_UserRegionMap.Remove(toAgentID); + HandleUndeliveredMessage(im, result); } - - // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); - HandleUndeliveredMessage(im, result); } /// -- cgit v1.1