diff options
author | Melanie | 2012-06-07 23:33:40 +0100 |
---|---|---|
committer | Melanie | 2012-06-07 23:33:40 +0100 |
commit | e8cd9fbbb748aed1caac4a5d20d7e723351349dd (patch) | |
tree | b901dfb2ebf4237a77aeebf1fbb929456a615693 /OpenSim/Region | |
parent | Remove a null ref when an avatar's attachment gets the avatar velocity (diff) | |
parent | Record the fact that child agents can have asset transactions. (diff) | |
download | opensim-SC_OLD-e8cd9fbbb748aed1caac4a5d20d7e723351349dd.zip opensim-SC_OLD-e8cd9fbbb748aed1caac4a5d20d7e723351349dd.tar.gz opensim-SC_OLD-e8cd9fbbb748aed1caac4a5d20d7e723351349dd.tar.bz2 opensim-SC_OLD-e8cd9fbbb748aed1caac4a5d20d7e723351349dd.tar.xz |
Merge branch 'master' into careminster
Conflicts:
OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
Diffstat (limited to 'OpenSim/Region')
6 files changed, 123 insertions, 57 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 28f9481..ac0e3e1 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs | |||
@@ -438,12 +438,16 @@ namespace OpenSim | |||
438 | } | 438 | } |
439 | } | 439 | } |
440 | 440 | ||
441 | private void WatchdogTimeoutHandler(System.Threading.Thread thread, int lastTick) | 441 | private void WatchdogTimeoutHandler(Watchdog.ThreadWatchdogInfo twi) |
442 | { | 442 | { |
443 | int now = Environment.TickCount & Int32.MaxValue; | 443 | int now = Environment.TickCount & Int32.MaxValue; |
444 | 444 | ||
445 | m_log.ErrorFormat("[WATCHDOG]: Timeout detected for thread \"{0}\". ThreadState={1}. Last tick was {2}ms ago", | 445 | m_log.ErrorFormat( |
446 | thread.Name, thread.ThreadState, now - lastTick); | 446 | "[WATCHDOG]: Timeout detected for thread \"{0}\". ThreadState={1}. Last tick was {2}ms ago. {3}", |
447 | twi.Thread.Name, | ||
448 | twi.Thread.ThreadState, | ||
449 | now - twi.LastTick, | ||
450 | twi.AlarmMethod != null ? string.Format("Data: {0}", twi.AlarmMethod()) : ""); | ||
447 | } | 451 | } |
448 | 452 | ||
449 | #region Console Commands | 453 | #region Console Commands |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index d310d65..3bdde3b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -163,6 +163,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
163 | 163 | ||
164 | private int m_malformedCount = 0; // Guard against a spamming attack | 164 | private int m_malformedCount = 0; // Guard against a spamming attack |
165 | 165 | ||
166 | /// <summary> | ||
167 | /// Record current outgoing client for monitoring purposes. | ||
168 | /// </summary> | ||
169 | private IClientAPI m_currentOutgoingClient; | ||
170 | |||
171 | /// <summary> | ||
172 | /// Recording current incoming client for monitoring purposes. | ||
173 | /// </summary> | ||
174 | private IClientAPI m_currentIncomingClient; | ||
175 | |||
166 | public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) | 176 | public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) |
167 | : base(listenIP, (int)port) | 177 | : base(listenIP, (int)port) |
168 | { | 178 | { |
@@ -244,19 +254,56 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
244 | if (m_scene == null) | 254 | if (m_scene == null) |
245 | throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); | 255 | throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); |
246 | 256 | ||
247 | m_log.Info("[LLUDPSERVER]: Starting the LLUDP server in " + (m_asyncPacketHandling ? "asynchronous" : "synchronous") + " mode"); | 257 | m_log.InfoFormat( |
258 | "[LLUDPSERVER]: Starting the LLUDP server in {0} mode", | ||
259 | m_asyncPacketHandling ? "asynchronous" : "synchronous"); | ||
248 | 260 | ||
249 | base.Start(m_recvBufferSize, m_asyncPacketHandling); | 261 | base.Start(m_recvBufferSize, m_asyncPacketHandling); |
250 | 262 | ||
251 | // Start the packet processing threads | 263 | // Start the packet processing threads |
252 | Watchdog.StartThread( | 264 | Watchdog.StartThread( |
253 | IncomingPacketHandler, "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false, true); | 265 | IncomingPacketHandler, |
266 | string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), | ||
267 | ThreadPriority.Normal, | ||
268 | false, | ||
269 | true, | ||
270 | GetWatchdogIncomingAlarmData, | ||
271 | Watchdog.WATCHDOG_TIMEOUT_MS); | ||
272 | |||
254 | Watchdog.StartThread( | 273 | Watchdog.StartThread( |
255 | OutgoingPacketHandler, "Outgoing Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false, true); | 274 | OutgoingPacketHandler, |
275 | string.Format("Outgoing Packets ({0})", m_scene.RegionInfo.RegionName), | ||
276 | ThreadPriority.Normal, | ||
277 | false, | ||
278 | true, | ||
279 | GetWatchdogOutgoingAlarmData, | ||
280 | Watchdog.WATCHDOG_TIMEOUT_MS); | ||
256 | 281 | ||
257 | m_elapsedMSSinceLastStatReport = Environment.TickCount; | 282 | m_elapsedMSSinceLastStatReport = Environment.TickCount; |
258 | } | 283 | } |
259 | 284 | ||
285 | /// <summary> | ||
286 | /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging. | ||
287 | /// </summary> | ||
288 | /// <returns></returns> | ||
289 | private string GetWatchdogIncomingAlarmData() | ||
290 | { | ||
291 | return string.Format( | ||
292 | "Client is {0}", | ||
293 | m_currentIncomingClient != null ? m_currentIncomingClient.Name : "none"); | ||
294 | } | ||
295 | |||
296 | /// <summary> | ||
297 | /// If the outgoing UDP thread times out, then return client that was being processed to help with debugging. | ||
298 | /// </summary> | ||
299 | /// <returns></returns> | ||
300 | private string GetWatchdogOutgoingAlarmData() | ||
301 | { | ||
302 | return string.Format( | ||
303 | "Client is {0}", | ||
304 | m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); | ||
305 | } | ||
306 | |||
260 | public new void Stop() | 307 | public new void Stop() |
261 | { | 308 | { |
262 | m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); | 309 | m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); |
@@ -1067,6 +1114,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1067 | client.IsLoggingOut = true; | 1114 | client.IsLoggingOut = true; |
1068 | client.Close(false); | 1115 | client.Close(false); |
1069 | } | 1116 | } |
1117 | else | ||
1118 | { | ||
1119 | m_log.WarnFormat( | ||
1120 | "[LLUDPSERVER]: Tried to remove client with id {0} but not such client in {1}", | ||
1121 | udpClient.AgentID, m_scene.RegionInfo.RegionName); | ||
1122 | } | ||
1070 | } | 1123 | } |
1071 | 1124 | ||
1072 | private void IncomingPacketHandler() | 1125 | private void IncomingPacketHandler() |
@@ -1175,6 +1228,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1175 | // client. m_packetSent will be set to true if a packet is sent | 1228 | // client. m_packetSent will be set to true if a packet is sent |
1176 | m_scene.ForEachClient(clientPacketHandler); | 1229 | m_scene.ForEachClient(clientPacketHandler); |
1177 | 1230 | ||
1231 | m_currentOutgoingClient = null; | ||
1232 | |||
1178 | // If nothing was sent, sleep for the minimum amount of time before a | 1233 | // If nothing was sent, sleep for the minimum amount of time before a |
1179 | // token bucket could get more tokens | 1234 | // token bucket could get more tokens |
1180 | if (!m_packetSent) | 1235 | if (!m_packetSent) |
@@ -1193,6 +1248,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1193 | 1248 | ||
1194 | private void ClientOutgoingPacketHandler(IClientAPI client) | 1249 | private void ClientOutgoingPacketHandler(IClientAPI client) |
1195 | { | 1250 | { |
1251 | m_currentOutgoingClient = client; | ||
1252 | |||
1196 | try | 1253 | try |
1197 | { | 1254 | { |
1198 | if (client is LLClientView) | 1255 | if (client is LLClientView) |
@@ -1218,8 +1275,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1218 | } | 1275 | } |
1219 | catch (Exception ex) | 1276 | catch (Exception ex) |
1220 | { | 1277 | { |
1221 | m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler iteration for " + client.Name + | 1278 | m_log.Error( |
1222 | " threw an exception: " + ex.Message, ex); | 1279 | string.Format("[LLUDPSERVER]: OutgoingPacketHandler iteration for {0} threw ", client.Name), ex); |
1223 | } | 1280 | } |
1224 | } | 1281 | } |
1225 | 1282 | ||
@@ -1245,6 +1302,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1245 | { | 1302 | { |
1246 | nticks++; | 1303 | nticks++; |
1247 | watch1.Start(); | 1304 | watch1.Start(); |
1305 | m_currentOutgoingClient = client; | ||
1306 | |||
1248 | try | 1307 | try |
1249 | { | 1308 | { |
1250 | if (client is LLClientView) | 1309 | if (client is LLClientView) |
@@ -1346,6 +1405,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1346 | // Make sure this client is still alive | 1405 | // Make sure this client is still alive |
1347 | if (m_scene.TryGetClient(udpClient.AgentID, out client)) | 1406 | if (m_scene.TryGetClient(udpClient.AgentID, out client)) |
1348 | { | 1407 | { |
1408 | m_currentIncomingClient = client; | ||
1409 | |||
1349 | try | 1410 | try |
1350 | { | 1411 | { |
1351 | // Process this packet | 1412 | // Process this packet |
@@ -1363,6 +1424,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1363 | m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", udpClient.AgentID, packet.Type); | 1424 | m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", udpClient.AgentID, packet.Type); |
1364 | m_log.Error(e.Message, e); | 1425 | m_log.Error(e.Message, e); |
1365 | } | 1426 | } |
1427 | finally | ||
1428 | { | ||
1429 | m_currentIncomingClient = null; | ||
1430 | } | ||
1366 | } | 1431 | } |
1367 | else | 1432 | else |
1368 | { | 1433 | { |
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs index 874693e..7081989 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs | |||
@@ -42,8 +42,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
42 | public class AssetTransactionModule : INonSharedRegionModule, | 42 | public class AssetTransactionModule : INonSharedRegionModule, |
43 | IAgentAssetTransactions | 43 | IAgentAssetTransactions |
44 | { | 44 | { |
45 | // private static readonly ILog m_log = LogManager.GetLogger( | 45 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
46 | // MethodBase.GetCurrentMethod().DeclaringType); | ||
47 | 46 | ||
48 | protected Scene m_Scene; | 47 | protected Scene m_Scene; |
49 | private bool m_dumpAssetsToFile = false; | 48 | private bool m_dumpAssetsToFile = false; |
@@ -209,15 +208,15 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
209 | /// and comes through this method. | 208 | /// and comes through this method. |
210 | /// </summary> | 209 | /// </summary> |
211 | /// <param name="remoteClient"></param> | 210 | /// <param name="remoteClient"></param> |
211 | /// <param name="part"></param> | ||
212 | /// <param name="transactionID"></param> | 212 | /// <param name="transactionID"></param> |
213 | /// <param name="item"></param> | 213 | /// <param name="item"></param> |
214 | public void HandleTaskItemUpdateFromTransaction(IClientAPI remoteClient, | 214 | public void HandleTaskItemUpdateFromTransaction( |
215 | SceneObjectPart part, UUID transactionID, | 215 | IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) |
216 | TaskInventoryItem item) | ||
217 | { | 216 | { |
218 | // m_log.DebugFormat( | 217 | m_log.DebugFormat( |
219 | // "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0}", | 218 | "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", |
220 | // item.Name); | 219 | item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName); |
221 | 220 | ||
222 | AgentAssetTransactions transactions = | 221 | AgentAssetTransactions transactions = |
223 | GetUserTransactions(remoteClient.AgentId); | 222 | GetUserTransactions(remoteClient.AgentId); |
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 31820e0..d30c2e2 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs | |||
@@ -216,7 +216,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
216 | } | 216 | } |
217 | else | 217 | else |
218 | { | 218 | { |
219 | IAgentAssetTransactions agentTransactions = m_Scene.RequestModuleInterface<IAgentAssetTransactions>(); | 219 | IAgentAssetTransactions agentTransactions = m_Scene.AgentTransactionsModule; |
220 | if (agentTransactions != null) | 220 | if (agentTransactions != null) |
221 | { | 221 | { |
222 | agentTransactions.HandleItemCreationFromTransaction( | 222 | agentTransactions.HandleItemCreationFromTransaction( |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 270b01b..e1281a6 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | |||
@@ -435,10 +435,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
435 | } | 435 | } |
436 | else | 436 | else |
437 | { | 437 | { |
438 | IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>(); | 438 | if (AgentTransactionsModule != null) |
439 | if (agentTransactions != null) | ||
440 | { | 439 | { |
441 | agentTransactions.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); | 440 | AgentTransactionsModule.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); |
442 | } | 441 | } |
443 | } | 442 | } |
444 | } | 443 | } |
@@ -1566,21 +1565,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1566 | // Only look for an uploaded updated asset if we are passed a transaction ID. This is only the | 1565 | // Only look for an uploaded updated asset if we are passed a transaction ID. This is only the |
1567 | // case for updates uploded through UDP. Updates uploaded via a capability (e.g. a script update) | 1566 | // case for updates uploded through UDP. Updates uploaded via a capability (e.g. a script update) |
1568 | // will not pass in a transaction ID in the update message. | 1567 | // will not pass in a transaction ID in the update message. |
1569 | if (transactionID != UUID.Zero) | 1568 | if (transactionID != UUID.Zero && AgentTransactionsModule != null) |
1570 | { | 1569 | { |
1571 | IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>(); | 1570 | AgentTransactionsModule.HandleTaskItemUpdateFromTransaction( |
1572 | if (agentTransactions != null) | 1571 | remoteClient, part, transactionID, currentItem); |
1573 | { | 1572 | |
1574 | agentTransactions.HandleTaskItemUpdateFromTransaction( | 1573 | // if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) |
1575 | remoteClient, part, transactionID, currentItem); | 1574 | // remoteClient.SendAgentAlertMessage("Notecard saved", false); |
1576 | 1575 | // else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) | |
1577 | // if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) | 1576 | // remoteClient.SendAgentAlertMessage("Script saved", false); |
1578 | // remoteClient.SendAgentAlertMessage("Notecard saved", false); | 1577 | // else |
1579 | // else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) | 1578 | // remoteClient.SendAgentAlertMessage("Item saved", false); |
1580 | // remoteClient.SendAgentAlertMessage("Script saved", false); | ||
1581 | // else | ||
1582 | // remoteClient.SendAgentAlertMessage("Item saved", false); | ||
1583 | } | ||
1584 | } | 1579 | } |
1585 | 1580 | ||
1586 | // Base ALWAYS has move | 1581 | // Base ALWAYS has move |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 9c80d3e..78fbd3b 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -521,6 +521,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
521 | 521 | ||
522 | public IAttachmentsModule AttachmentsModule { get; set; } | 522 | public IAttachmentsModule AttachmentsModule { get; set; } |
523 | public IEntityTransferModule EntityTransferModule { get; private set; } | 523 | public IEntityTransferModule EntityTransferModule { get; private set; } |
524 | public IAgentAssetTransactions AgentTransactionsModule { get; private set; } | ||
524 | 525 | ||
525 | public IAvatarFactoryModule AvatarFactory | 526 | public IAvatarFactoryModule AvatarFactory |
526 | { | 527 | { |
@@ -1289,6 +1290,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1289 | m_capsModule = RequestModuleInterface<ICapabilitiesModule>(); | 1290 | m_capsModule = RequestModuleInterface<ICapabilitiesModule>(); |
1290 | EntityTransferModule = RequestModuleInterface<IEntityTransferModule>(); | 1291 | EntityTransferModule = RequestModuleInterface<IEntityTransferModule>(); |
1291 | m_groupsModule = RequestModuleInterface<IGroupsModule>(); | 1292 | m_groupsModule = RequestModuleInterface<IGroupsModule>(); |
1293 | AgentTransactionsModule = RequestModuleInterface<IAgentAssetTransactions>(); | ||
1292 | } | 1294 | } |
1293 | 1295 | ||
1294 | #endregion | 1296 | #endregion |
@@ -3428,32 +3430,33 @@ namespace OpenSim.Region.Framework.Scenes | |||
3428 | { | 3430 | { |
3429 | m_eventManager.TriggerOnRemovePresence(agentID); | 3431 | m_eventManager.TriggerOnRemovePresence(agentID); |
3430 | 3432 | ||
3431 | if (AttachmentsModule != null && !isChildAgent && avatar.PresenceType != PresenceType.Npc) | 3433 | if (!isChildAgent) |
3432 | { | 3434 | { |
3433 | IUserManagement uMan = RequestModuleInterface<IUserManagement>(); | 3435 | if (AttachmentsModule != null && avatar.PresenceType != PresenceType.Npc) |
3434 | // Don't save attachments for HG visitors, it | ||
3435 | // messes up their inventory. When a HG visitor logs | ||
3436 | // out on a foreign grid, their attachments will be | ||
3437 | // reloaded in the state they were in when they left | ||
3438 | // the home grid. This is best anyway as the visited | ||
3439 | // grid may use an incompatible script engine. | ||
3440 | if (uMan == null || uMan.IsLocalGridUser(avatar.UUID)) | ||
3441 | AttachmentsModule.SaveChangedAttachments(avatar, false); | ||
3442 | } | ||
3443 | |||
3444 | ForEachClient( | ||
3445 | delegate(IClientAPI client) | ||
3446 | { | 3436 | { |
3447 | //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway | 3437 | IUserManagement uMan = RequestModuleInterface<IUserManagement>(); |
3448 | try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } | 3438 | // Don't save attachments for HG visitors, it |
3449 | catch (NullReferenceException) { } | 3439 | // messes up their inventory. When a HG visitor logs |
3450 | }); | 3440 | // out on a foreign grid, their attachments will be |
3451 | 3441 | // reloaded in the state they were in when they left | |
3452 | IAgentAssetTransactions agentTransactions = this.RequestModuleInterface<IAgentAssetTransactions>(); | 3442 | // the home grid. This is best anyway as the visited |
3453 | if (agentTransactions != null) | 3443 | // grid may use an incompatible script engine. |
3454 | { | 3444 | if (uMan == null || uMan.IsLocalGridUser(avatar.UUID)) |
3455 | agentTransactions.RemoveAgentAssetTransactions(agentID); | 3445 | AttachmentsModule.SaveChangedAttachments(avatar, false); |
3446 | } | ||
3447 | |||
3448 | ForEachClient( | ||
3449 | delegate(IClientAPI client) | ||
3450 | { | ||
3451 | //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway | ||
3452 | try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } | ||
3453 | catch (NullReferenceException) { } | ||
3454 | }); | ||
3456 | } | 3455 | } |
3456 | |||
3457 | // It's possible for child agents to have transactions if changes are being made cross-border. | ||
3458 | if (AgentTransactionsModule != null) | ||
3459 | AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); | ||
3457 | } | 3460 | } |
3458 | finally | 3461 | finally |
3459 | { | 3462 | { |