From 999cb4b20cc20a24c7b9fbce4c31b13f8bf36cb5 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 23 Nov 2012 04:40:49 +0000 Subject: Make "show threads" and "thread abort" console commands available on all servers --- OpenSim/Framework/Servers/BaseOpenSimServer.cs | 103 +------------------------ OpenSim/Framework/Servers/ServerBase.cs | 92 ++++++++++++++++++++++ OpenSim/Framework/Util.cs | 16 ++-- 3 files changed, 103 insertions(+), 108 deletions(-) diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 3f66ab5..c0dc907 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -27,7 +27,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Reflection; using System.Text; @@ -99,19 +98,6 @@ namespace OpenSim.Framework.Servers m_console.Commands.AddCommand("General", false, "shutdown", "shutdown", "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 ", - "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())); } /// @@ -144,54 +130,6 @@ namespace OpenSim.Framework.Servers } /// - /// Get a report about the registered threads in this server. - /// - 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(); - } - - /// /// Performs initialisation of the scene, such as loading configuration from disk. /// public virtual void Startup() @@ -231,46 +169,7 @@ namespace OpenSim.Framework.Servers private void HandleQuit(string module, string[] args) { Shutdown(); - } - - public override void HandleShow(string module, string[] cmd) - { - base.HandleShow(module, cmd); - - List args = new List(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 "); - 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 { // Secret uuid for the simulator diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index b8bc27e..47baac8 100644 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs @@ -27,16 +27,19 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Reflection; using System.Text; using System.Text.RegularExpressions; +using System.Threading; using log4net; using log4net.Appender; using log4net.Core; using log4net.Repository; using Nini.Config; using OpenSim.Framework.Console; +using OpenSim.Framework.Monitoring; namespace OpenSim.Framework.Servers { @@ -211,6 +214,22 @@ namespace OpenSim.Framework.Servers "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 ", + "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( "General", false, "force gc", "force gc", "Manually invoke runtime garbage collection. For debugging purposes", @@ -244,6 +263,10 @@ namespace OpenSim.Framework.Servers case "uptime": Notice(GetUptimeReport()); break; + + case "threads": + Notice(GetThreadsReport()); + break; } } @@ -556,6 +579,75 @@ namespace OpenSim.Framework.Servers } /// + /// Get a report about the registered threads in this server. + /// + 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 "); + 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); + } + + /// /// Console output is only possible if a console has been established. /// That is something that cannot be determined within this class. So /// all attempts to use the console MUST be verified. diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index c369dbc..a0c54a0 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -1741,12 +1741,16 @@ namespace OpenSim.Framework StringBuilder sb = new StringBuilder(); if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) { - threadPoolUsed = "SmartThreadPool"; - maxThreads = m_ThreadPool.MaxThreads; - minThreads = m_ThreadPool.MinThreads; - inUseThreads = m_ThreadPool.InUseThreads; - allocatedThreads = m_ThreadPool.ActiveThreads; - waitingCallbacks = m_ThreadPool.WaitingCallbacks; + // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool. + if (m_ThreadPool != null) + { + threadPoolUsed = "SmartThreadPool"; + maxThreads = m_ThreadPool.MaxThreads; + minThreads = m_ThreadPool.MinThreads; + inUseThreads = m_ThreadPool.InUseThreads; + allocatedThreads = m_ThreadPool.ActiveThreads; + waitingCallbacks = m_ThreadPool.WaitingCallbacks; + } } else if ( FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem -- cgit v1.1