Make "show threads" and "thread abort" console commands available on all servers

0.7.4-extended
Justin Clark-Casey (justincc) 2012-11-23 04:40:49 +00:00
parent 1d75570c59
commit ace552ecc5
3 changed files with 103 additions and 108 deletions

View File

@ -27,7 +27,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
@ -99,19 +98,6 @@ namespace OpenSim.Framework.Servers
m_console.Commands.AddCommand("General", false, "shutdown", m_console.Commands.AddCommand("General", false, "shutdown",
"shutdown", "shutdown",
"Quit the application", HandleQuit); "Quit the application", HandleQuit);
m_console.Commands.AddCommand("General", false, "show threads",
"show threads",
"Show thread status", HandleShow);
m_console.Commands.AddCommand("General", false, "threads abort",
"threads abort <thread-id>",
"Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
m_console.Commands.AddCommand("General", false, "threads show",
"threads show",
"Show thread status. Synonym for \"show threads\"",
(string module, string[] args) => Notice(GetThreadsReport()));
} }
/// <summary> /// <summary>
@ -143,54 +129,6 @@ namespace OpenSim.Framework.Servers
m_log.Debug(sb); m_log.Debug(sb);
} }
/// <summary>
/// Get a report about the registered threads in this server.
/// </summary>
protected string GetThreadsReport()
{
// This should be a constant field.
string reportFormat = "{0,6} {1,35} {2,16} {3,13} {4,10} {5,30}";
StringBuilder sb = new StringBuilder();
Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreadsInfo();
sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine);
int timeNow = Environment.TickCount & Int32.MaxValue;
sb.AppendFormat(reportFormat, "ID", "NAME", "LAST UPDATE (MS)", "LIFETIME (MS)", "PRIORITY", "STATE");
sb.Append(Environment.NewLine);
foreach (Watchdog.ThreadWatchdogInfo twi in threads)
{
Thread t = twi.Thread;
sb.AppendFormat(
reportFormat,
t.ManagedThreadId,
t.Name,
timeNow - twi.LastTick,
timeNow - twi.FirstTick,
t.Priority,
t.ThreadState);
sb.Append("\n");
}
sb.Append("\n");
// For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting
// zero active threads.
int totalThreads = Process.GetCurrentProcess().Threads.Count;
if (totalThreads > 0)
sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
sb.Append("Main threadpool (excluding script engine pools)\n");
sb.Append(Util.GetThreadPoolReport());
return sb.ToString();
}
/// <summary> /// <summary>
/// Performs initialisation of the scene, such as loading configuration from disk. /// Performs initialisation of the scene, such as loading configuration from disk.
/// </summary> /// </summary>
@ -233,45 +171,6 @@ namespace OpenSim.Framework.Servers
Shutdown(); Shutdown();
} }
public override void HandleShow(string module, string[] cmd)
{
base.HandleShow(module, cmd);
List<string> args = new List<string>(cmd);
args.RemoveAt(0);
string[] showParams = args.ToArray();
switch (showParams[0])
{
case "threads":
Notice(GetThreadsReport());
break;
}
}
public virtual void HandleThreadsAbort(string module, string[] cmd)
{
if (cmd.Length != 3)
{
MainConsole.Instance.Output("Usage: threads abort <thread-id>");
return;
}
int threadId;
if (!int.TryParse(cmd[2], out threadId))
{
MainConsole.Instance.Output("ERROR: Thread id must be an integer");
return;
}
if (Watchdog.AbortThread(threadId))
MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId);
else
MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId);
}
public string osSecret { public string osSecret {
// Secret uuid for the simulator // Secret uuid for the simulator
get { return m_osSecret; } get { return m_osSecret; }

View File

@ -27,16 +27,19 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading;
using log4net; using log4net;
using log4net.Appender; using log4net.Appender;
using log4net.Core; using log4net.Core;
using log4net.Repository; using log4net.Repository;
using Nini.Config; using Nini.Config;
using OpenSim.Framework.Console; using OpenSim.Framework.Console;
using OpenSim.Framework.Monitoring;
namespace OpenSim.Framework.Servers namespace OpenSim.Framework.Servers
{ {
@ -210,6 +213,22 @@ namespace OpenSim.Framework.Servers
"command-script <script>", "command-script <script>",
"Run a command script from file", HandleScript); "Run a command script from file", HandleScript);
m_console.Commands.AddCommand(
"General", false, "show threads",
"show threads",
"Show thread status", HandleShow);
m_console.Commands.AddCommand(
"General", false, "threads abort",
"threads abort <thread-id>",
"Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
m_console.Commands.AddCommand(
"General", false, "threads show",
"threads show",
"Show thread status. Synonym for \"show threads\"",
(string module, string[] args) => Notice(GetThreadsReport()));
m_console.Commands.AddCommand( m_console.Commands.AddCommand(
"General", false, "force gc", "General", false, "force gc",
"force gc", "force gc",
@ -244,6 +263,10 @@ namespace OpenSim.Framework.Servers
case "uptime": case "uptime":
Notice(GetUptimeReport()); Notice(GetUptimeReport());
break; break;
case "threads":
Notice(GetThreadsReport());
break;
} }
} }
@ -555,6 +578,75 @@ namespace OpenSim.Framework.Servers
return String.Format("Version: {0} (interface version {1})", m_version, VersionInfo.MajorInterfaceVersion); return String.Format("Version: {0} (interface version {1})", m_version, VersionInfo.MajorInterfaceVersion);
} }
/// <summary>
/// Get a report about the registered threads in this server.
/// </summary>
protected string GetThreadsReport()
{
// This should be a constant field.
string reportFormat = "{0,6} {1,35} {2,16} {3,13} {4,10} {5,30}";
StringBuilder sb = new StringBuilder();
Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreadsInfo();
sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine);
int timeNow = Environment.TickCount & Int32.MaxValue;
sb.AppendFormat(reportFormat, "ID", "NAME", "LAST UPDATE (MS)", "LIFETIME (MS)", "PRIORITY", "STATE");
sb.Append(Environment.NewLine);
foreach (Watchdog.ThreadWatchdogInfo twi in threads)
{
Thread t = twi.Thread;
sb.AppendFormat(
reportFormat,
t.ManagedThreadId,
t.Name,
timeNow - twi.LastTick,
timeNow - twi.FirstTick,
t.Priority,
t.ThreadState);
sb.Append("\n");
}
sb.Append("\n");
// For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting
// zero active threads.
int totalThreads = Process.GetCurrentProcess().Threads.Count;
if (totalThreads > 0)
sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
sb.Append("Main threadpool (excluding script engine pools)\n");
sb.Append(Util.GetThreadPoolReport());
return sb.ToString();
}
public virtual void HandleThreadsAbort(string module, string[] cmd)
{
if (cmd.Length != 3)
{
MainConsole.Instance.Output("Usage: threads abort <thread-id>");
return;
}
int threadId;
if (!int.TryParse(cmd[2], out threadId))
{
MainConsole.Instance.Output("ERROR: Thread id must be an integer");
return;
}
if (Watchdog.AbortThread(threadId))
MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId);
else
MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId);
}
/// <summary> /// <summary>
/// Console output is only possible if a console has been established. /// Console output is only possible if a console has been established.
/// That is something that cannot be determined within this class. So /// That is something that cannot be determined within this class. So

View File

@ -1740,6 +1740,9 @@ namespace OpenSim.Framework
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
{
// ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
if (m_ThreadPool != null)
{ {
threadPoolUsed = "SmartThreadPool"; threadPoolUsed = "SmartThreadPool";
maxThreads = m_ThreadPool.MaxThreads; maxThreads = m_ThreadPool.MaxThreads;
@ -1748,6 +1751,7 @@ namespace OpenSim.Framework
allocatedThreads = m_ThreadPool.ActiveThreads; allocatedThreads = m_ThreadPool.ActiveThreads;
waitingCallbacks = m_ThreadPool.WaitingCallbacks; waitingCallbacks = m_ThreadPool.WaitingCallbacks;
} }
}
else if ( else if (
FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem
|| FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem) || FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)