From bcbd450fe441e94d6c0f547055b4e95f75a5b0d0 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Mon, 20 Aug 2012 20:24:54 +0100
Subject: Add --force flag to "kick user" console command to allow bypassing of
recent race condition checks.
This is to allow a second attempt to remove an avatar even if "show connections" shows them as already inactive (i.e. close has already been attempted once).
You should only attempt --force if a normal kick fails.
This is partly for diagnostics as we have seen some connections occasionally remain on lbsa plaza even if they are registered as inactive.
This is not a permanent solution and may not work anyway - the ultimate solution is to stop this problem from happening in the first place.
---
OpenSim/Framework/IClientAPI.cs | 14 +++++++++++++
OpenSim/Region/Application/OpenSim.cs | 24 +++++++++++++++-------
.../Caps/EventQueue/Tests/EventQueueTests.cs | 2 +-
.../Region/ClientStack/Linden/UDP/LLClientView.cs | 14 ++++++++-----
.../Attachments/Tests/AttachmentsModuleTests.cs | 2 +-
.../EntityTransfer/EntityTransferModule.cs | 2 +-
.../Simulation/LocalSimulationConnector.cs | 2 +-
OpenSim/Region/Framework/Scenes/Scene.cs | 9 +++++---
.../Scenes/Tests/ScenePresenceAgentTests.cs | 2 +-
.../Server/IRCClientView.cs | 5 +++++
.../Region/OptionalModules/World/NPC/NPCAvatar.cs | 5 +++++
.../Shared/Api/Implementation/OSSL_Api.cs | 4 ++--
OpenSim/Tests/Common/Mock/TestClient.cs | 5 +++++
prebuild.xml | 1 +
14 files changed, 69 insertions(+), 22 deletions(-)
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index d5952c4..8a63bff 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -1033,7 +1033,21 @@ namespace OpenSim.Framework
void InPacket(object NewPack);
void ProcessInPacket(Packet NewPack);
+
+ ///
+ /// Close this client
+ ///
void Close();
+
+ ///
+ /// Close this client
+ ///
+ ///
+ /// If true, attempts the close without checking active status. You do not want to try this except as a last
+ /// ditch attempt where Active == false but the ScenePresence still exists.
+ ///
+ void Close(bool force);
+
void Kick(string message);
///
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 6bbab35..1fc11f5 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -35,6 +35,7 @@ using System.Text;
using System.Text.RegularExpressions;
using System.Timers;
using log4net;
+using NDesk.Options;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
@@ -310,8 +311,11 @@ namespace OpenSim
"Change the scale of a named prim", HandleEditScale);
m_console.Commands.AddCommand("Users", false, "kick user",
- "kick user [message]",
- "Kick a user off the simulator", KickUserCommand);
+ "kick user [--force] [message]",
+ "Kick a user off the simulator",
+ "The --force option will kick the user without any checks to see whether it's already in the process of closing\n"
+ + "Only use this option if you are sure the avatar is inactive and a normal kick user operation does not removed them",
+ KickUserCommand);
m_console.Commands.AddCommand("Users", false, "show users",
"show users [full]",
@@ -453,11 +457,17 @@ namespace OpenSim
/// name of avatar to kick
private void KickUserCommand(string module, string[] cmdparams)
{
- if (cmdparams.Length < 4)
+ bool force = false;
+
+ OptionSet options = new OptionSet().Add("f|force", delegate (string v) { force = v != null; });
+
+ List mainParams = options.Parse(cmdparams);
+
+ if (mainParams.Count < 4)
return;
string alert = null;
- if (cmdparams.Length > 4)
+ if (mainParams.Count > 4)
alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4));
IList agents = SceneManager.GetCurrentSceneAvatars();
@@ -466,8 +476,8 @@ namespace OpenSim
{
RegionInfo regionInfo = presence.Scene.RegionInfo;
- if (presence.Firstname.ToLower().Contains(cmdparams[2].ToLower()) &&
- presence.Lastname.ToLower().Contains(cmdparams[3].ToLower()))
+ if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) &&
+ presence.Lastname.ToLower().Contains(mainParams[3].ToLower()))
{
MainConsole.Instance.Output(
String.Format(
@@ -480,7 +490,7 @@ namespace OpenSim
else
presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n");
- presence.Scene.IncomingCloseAgent(presence.UUID);
+ presence.Scene.IncomingCloseAgent(presence.UUID, force);
}
}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index cd70410..d604cf6 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
UUID spId = TestHelpers.ParseTail(0x1);
SceneHelpers.AddScenePresence(m_scene, spId);
- m_scene.IncomingCloseAgent(spId);
+ m_scene.IncomingCloseAgent(spId, false);
// TODO: Add more assertions for the other aspects of event queues
Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0));
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 22b3d35..148d0e0 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -487,16 +487,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Client Methods
- ///
- /// Close down the client view
- ///
public void Close()
{
+ Close(false);
+ }
+
+ public void Close(bool force)
+ {
// We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
// a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
lock (CloseSyncLock)
{
- if (!IsActive)
+ // We still perform a force close inside the sync lock since this is intended to attempt close where
+ // there is some unidentified connection problem, not where we have issues due to deadlock
+ if (!IsActive && !force)
return;
IsActive = false;
@@ -11989,7 +11993,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
Kick(reason);
Thread.Sleep(1000);
- Close();
+ Disconnect();
}
public void Disconnect()
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 1d13f75..82c6390 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -461,7 +461,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
SceneObjectGroup rezzedAtt = presence.GetAttachments()[0];
- scene.IncomingCloseAgent(presence.UUID);
+ scene.IncomingCloseAgent(presence.UUID, false);
// Check that we can't retrieve this attachment from the scene.
Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null);
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 46738f6..c63b0a4 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -644,7 +644,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// an agent cannot teleport back to this region if it has teleported away.
Thread.Sleep(2000);
- sp.Scene.IncomingCloseAgent(sp.UUID);
+ sp.Scene.IncomingCloseAgent(sp.UUID, false);
}
else
{
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index 09a3bd6..1e52d37 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -312,7 +312,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
// s.RegionInfo.RegionName, destination.RegionHandle);
- Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id); });
+ Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id, false); });
return true;
}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index d2d6aba..ad74189 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -4116,16 +4116,19 @@ namespace OpenSim.Region.Framework.Scenes
///
/// Tell a single agent to disconnect from the region.
///
- ///
///
- public bool IncomingCloseAgent(UUID agentID)
+ ///
+ /// Force the agent to close even if it might be in the middle of some other operation. You do not want to
+ /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
+ ///
+ public bool IncomingCloseAgent(UUID agentID, bool force)
{
//m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
ScenePresence presence = m_sceneGraph.GetScenePresence(agentID);
if (presence != null)
{
- presence.ControllingClient.Close();
+ presence.ControllingClient.Close(force);
return true;
}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
index 5758869..5faf131 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
@@ -141,7 +141,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
TestScene scene = new SceneHelpers().SetupScene();
ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
- scene.IncomingCloseAgent(sp.UUID);
+ scene.IncomingCloseAgent(sp.UUID, false);
Assert.That(scene.GetScenePresence(sp.UUID), Is.Null);
Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null);
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index bae25cd..e93bd7c 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -886,6 +886,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
public void Close()
{
+ Close(false);
+ }
+
+ public void Close(bool force)
+ {
Disconnect();
}
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 67989ba..a8e4d90 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -901,6 +901,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public void Close()
{
+ Close(false);
+ }
+
+ public void Close(bool force)
+ {
// Remove ourselves from the scene
m_scene.RemoveClient(AgentId, false);
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 8936cb2..1e8b51b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -2877,7 +2877,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
avatar.SpeedModifier = (float)SpeedModifier;
}
- public void osKickAvatar(string FirstName,string SurName,string alert)
+ public void osKickAvatar(string FirstName, string SurName, string alert)
{
CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar");
m_host.AddScriptLPS(1);
@@ -2891,7 +2891,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
sp.ControllingClient.Kick(alert);
// ...and close on our side
- sp.Scene.IncomingCloseAgent(sp.UUID);
+ sp.Scene.IncomingCloseAgent(sp.UUID, false);
}
});
}
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index 89c4f11..bb8b935 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -934,6 +934,11 @@ namespace OpenSim.Tests.Common.Mock
public void Close()
{
+ Close(false);
+ }
+
+ public void Close(bool force)
+ {
// Fire the callback for this connection closing
// This is necesary to get the presence detector to notice that a client has logged out.
if (OnConnectionClosed != null)
diff --git a/prebuild.xml b/prebuild.xml
index b4f4464..1765899 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -1760,6 +1760,7 @@
+
--
cgit v1.1