Make "show threads" and "thread abort" console commands available on all servers
parent
1d75570c59
commit
ace552ecc5
|
@ -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>
|
||||||
|
@ -231,46 +169,7 @@ namespace OpenSim.Framework.Servers
|
||||||
private void HandleQuit(string module, string[] args)
|
private void HandleQuit(string module, string[] args)
|
||||||
{
|
{
|
||||||
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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1741,12 +1741,16 @@ namespace OpenSim.Framework
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
|
if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
|
||||||
{
|
{
|
||||||
threadPoolUsed = "SmartThreadPool";
|
// ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
|
||||||
maxThreads = m_ThreadPool.MaxThreads;
|
if (m_ThreadPool != null)
|
||||||
minThreads = m_ThreadPool.MinThreads;
|
{
|
||||||
inUseThreads = m_ThreadPool.InUseThreads;
|
threadPoolUsed = "SmartThreadPool";
|
||||||
allocatedThreads = m_ThreadPool.ActiveThreads;
|
maxThreads = m_ThreadPool.MaxThreads;
|
||||||
waitingCallbacks = m_ThreadPool.WaitingCallbacks;
|
minThreads = m_ThreadPool.MinThreads;
|
||||||
|
inUseThreads = m_ThreadPool.InUseThreads;
|
||||||
|
allocatedThreads = m_ThreadPool.ActiveThreads;
|
||||||
|
waitingCallbacks = m_ThreadPool.WaitingCallbacks;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (
|
else if (
|
||||||
FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem
|
FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem
|
||||||
|
|
Loading…
Reference in New Issue