diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 51606b4ee8..556942cca7 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -741,22 +741,19 @@ namespace OpenSim.Framework
string Name { get; }
///
- /// True if the client is active (sending and receiving new UDP messages). False if the client is closing.
+ /// True if the client is active (sending and receiving new UDP messages). False if the client is being closed.
///
bool IsActive { get; set; }
///
- /// Set if the client is closing due to a logout request or because of too much time since last ack.
+ /// Set if the client is closing due to a logout request
///
///
/// Do not use this flag if you want to know if the client is closing, since it will not be set in other
/// circumstances (e.g. if a child agent is closed or the agent is kicked off the simulator). Use IsActive
- /// instead.
+ /// instead with a IClientAPI.SceneAgent.IsChildAgent check if necessary.
///
/// Only set for root agents.
- ///
- /// TODO: Too much time since last ack should probably be a separate property, or possibly part of a state
- /// machine.
///
bool IsLoggingOut { get; set; }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 2036f61f22..37d29439a6 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -555,15 +555,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (udpClient.IsPaused)
timeoutTicks = m_pausedAckTimeout;
- if (!client.IsLoggingOut &&
+ if (client.IsActive &&
(Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > timeoutTicks)
{
- m_log.WarnFormat(
- "[LLUDPSERVER]: Ack timeout for {0} {1}, disconnecting",
- client.Name, client.AgentId);
+ // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
+ // though it's set later on by LLClientView.Close()
+ client.IsActive = false;
- StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
- LogoutClientDueToTimeout(client);
+ // Fire this out on a different thread so that we don't hold up outgoing packet processing for
+ // everybody else if this is being called due to an ack timeout.
+ // This is the same as processing as the async process of a logout request.
+ Util.FireAndForget(o => DeactivateClientDueToTimeout(client));
return;
}
@@ -792,7 +794,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
Interlocked.Increment(ref udpClient.PacketsReceived);
int now = Environment.TickCount & Int32.MaxValue;
- udpClient.TickLastPacketReceived = now;
+// udpClient.TickLastPacketReceived = now;
#region ACK Receiving
@@ -1113,30 +1115,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return client;
}
- private void RemoveClient(IClientAPI client)
+ ///
+ /// Deactivates the client if we don't receive any packets within a certain amount of time (default 60 seconds).
+ ///
+ ///
+ /// If a connection is active then we will always receive packets even if nothing else is happening, due to
+ /// regular client pings.
+ ///
+ ///
+ private void DeactivateClientDueToTimeout(IClientAPI client)
{
- // We must set IsLoggingOut synchronously so that we can stop the packet loop reinvoking this method.
- client.IsLoggingOut = true;
+ // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even
+ // though it's set later on by LLClientView.Close()
+ client.IsActive = false;
- // Fire this out on a different thread so that we don't hold up outgoing packet processing for
- // everybody else if this is being called due to an ack timeout.
- // This is the same as processing as the async process of a logout request.
- Util.FireAndForget(o => client.Close());
- }
+ m_log.WarnFormat(
+ "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}",
+ client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName);
- private void LogoutClientDueToTimeout(IClientAPI client)
- {
- // We must set IsLoggingOut synchronously so that we can stop the packet loop reinvoking this method.
- client.IsLoggingOut = true;
+ StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
- // Fire this out on a different thread so that we don't hold up outgoing packet processing for
- // everybody else if this is being called due to an ack timeout.
- // This is the same as processing as the async process of a logout request.
- Util.FireAndForget(
- o =>
- { if (!client.SceneAgent.IsChildAgent)
- client.Kick("Simulator logged you out due to connection timeout");
- client.Close(); });
+ if (!client.SceneAgent.IsChildAgent)
+ client.Kick("Simulator logged you out due to connection timeout");
+
+ client.Close();
}
private void IncomingPacketHandler()
@@ -1450,8 +1452,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
protected void LogoutHandler(IClientAPI client)
{
client.SendLogoutPacket();
+
if (!client.IsLoggingOut)
- RemoveClient(client);
+ {
+ client.IsLoggingOut = true;
+ client.Close();
+ }
}
}
}
\ No newline at end of file