diff options
author | Justin Clark-Casey (justincc) | 2012-11-23 04:40:49 +0000 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2012-11-23 04:40:49 +0000 |
commit | 999cb4b20cc20a24c7b9fbce4c31b13f8bf36cb5 (patch) | |
tree | a73ecf998adad5920e94c570743e6897ae1a87f4 /OpenSim | |
parent | Make "force gc" console command available across all servers (diff) | |
download | opensim-SC-999cb4b20cc20a24c7b9fbce4c31b13f8bf36cb5.zip opensim-SC-999cb4b20cc20a24c7b9fbce4c31b13f8bf36cb5.tar.gz opensim-SC-999cb4b20cc20a24c7b9fbce4c31b13f8bf36cb5.tar.bz2 opensim-SC-999cb4b20cc20a24c7b9fbce4c31b13f8bf36cb5.tar.xz |
Make "show threads" and "thread abort" console commands available on all servers
Diffstat (limited to 'OpenSim')
-rw-r--r-- | OpenSim/Framework/Servers/BaseOpenSimServer.cs | 103 | ||||
-rw-r--r-- | OpenSim/Framework/Servers/ServerBase.cs | 92 | ||||
-rw-r--r-- | 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 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Diagnostics; | ||
31 | using System.IO; | 30 | using System.IO; |
32 | using System.Reflection; | 31 | using System.Reflection; |
33 | using System.Text; | 32 | using System.Text; |
@@ -99,19 +98,6 @@ namespace OpenSim.Framework.Servers | |||
99 | m_console.Commands.AddCommand("General", false, "shutdown", | 98 | m_console.Commands.AddCommand("General", false, "shutdown", |
100 | "shutdown", | 99 | "shutdown", |
101 | "Quit the application", HandleQuit); | 100 | "Quit the application", HandleQuit); |
102 | |||
103 | m_console.Commands.AddCommand("General", false, "show threads", | ||
104 | "show threads", | ||
105 | "Show thread status", HandleShow); | ||
106 | |||
107 | m_console.Commands.AddCommand("General", false, "threads abort", | ||
108 | "threads abort <thread-id>", | ||
109 | "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort); | ||
110 | |||
111 | m_console.Commands.AddCommand("General", false, "threads show", | ||
112 | "threads show", | ||
113 | "Show thread status. Synonym for \"show threads\"", | ||
114 | (string module, string[] args) => Notice(GetThreadsReport())); | ||
115 | } | 101 | } |
116 | 102 | ||
117 | /// <summary> | 103 | /// <summary> |
@@ -144,54 +130,6 @@ namespace OpenSim.Framework.Servers | |||
144 | } | 130 | } |
145 | 131 | ||
146 | /// <summary> | 132 | /// <summary> |
147 | /// Get a report about the registered threads in this server. | ||
148 | /// </summary> | ||
149 | protected string GetThreadsReport() | ||
150 | { | ||
151 | // This should be a constant field. | ||
152 | string reportFormat = "{0,6} {1,35} {2,16} {3,13} {4,10} {5,30}"; | ||
153 | |||
154 | StringBuilder sb = new StringBuilder(); | ||
155 | Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreadsInfo(); | ||
156 | |||
157 | sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine); | ||
158 | |||
159 | int timeNow = Environment.TickCount & Int32.MaxValue; | ||
160 | |||
161 | sb.AppendFormat(reportFormat, "ID", "NAME", "LAST UPDATE (MS)", "LIFETIME (MS)", "PRIORITY", "STATE"); | ||
162 | sb.Append(Environment.NewLine); | ||
163 | |||
164 | foreach (Watchdog.ThreadWatchdogInfo twi in threads) | ||
165 | { | ||
166 | Thread t = twi.Thread; | ||
167 | |||
168 | sb.AppendFormat( | ||
169 | reportFormat, | ||
170 | t.ManagedThreadId, | ||
171 | t.Name, | ||
172 | timeNow - twi.LastTick, | ||
173 | timeNow - twi.FirstTick, | ||
174 | t.Priority, | ||
175 | t.ThreadState); | ||
176 | |||
177 | sb.Append("\n"); | ||
178 | } | ||
179 | |||
180 | sb.Append("\n"); | ||
181 | |||
182 | // For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting | ||
183 | // zero active threads. | ||
184 | int totalThreads = Process.GetCurrentProcess().Threads.Count; | ||
185 | if (totalThreads > 0) | ||
186 | sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); | ||
187 | |||
188 | sb.Append("Main threadpool (excluding script engine pools)\n"); | ||
189 | sb.Append(Util.GetThreadPoolReport()); | ||
190 | |||
191 | return sb.ToString(); | ||
192 | } | ||
193 | |||
194 | /// <summary> | ||
195 | /// Performs initialisation of the scene, such as loading configuration from disk. | 133 | /// Performs initialisation of the scene, such as loading configuration from disk. |
196 | /// </summary> | 134 | /// </summary> |
197 | public virtual void Startup() | 135 | public virtual void Startup() |
@@ -231,46 +169,7 @@ namespace OpenSim.Framework.Servers | |||
231 | private void HandleQuit(string module, string[] args) | 169 | private void HandleQuit(string module, string[] args) |
232 | { | 170 | { |
233 | Shutdown(); | 171 | Shutdown(); |
234 | } | 172 | } |
235 | |||
236 | public override void HandleShow(string module, string[] cmd) | ||
237 | { | ||
238 | base.HandleShow(module, cmd); | ||
239 | |||
240 | List<string> args = new List<string>(cmd); | ||
241 | |||
242 | args.RemoveAt(0); | ||
243 | |||
244 | string[] showParams = args.ToArray(); | ||
245 | |||
246 | switch (showParams[0]) | ||
247 | { | ||
248 | case "threads": | ||
249 | Notice(GetThreadsReport()); | ||
250 | break; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | public virtual void HandleThreadsAbort(string module, string[] cmd) | ||
255 | { | ||
256 | if (cmd.Length != 3) | ||
257 | { | ||
258 | MainConsole.Instance.Output("Usage: threads abort <thread-id>"); | ||
259 | return; | ||
260 | } | ||
261 | |||
262 | int threadId; | ||
263 | if (!int.TryParse(cmd[2], out threadId)) | ||
264 | { | ||
265 | MainConsole.Instance.Output("ERROR: Thread id must be an integer"); | ||
266 | return; | ||
267 | } | ||
268 | |||
269 | if (Watchdog.AbortThread(threadId)) | ||
270 | MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId); | ||
271 | else | ||
272 | MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId); | ||
273 | } | ||
274 | 173 | ||
275 | public string osSecret { | 174 | public string osSecret { |
276 | // Secret uuid for the simulator | 175 | // 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 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Diagnostics; | ||
30 | using System.IO; | 31 | using System.IO; |
31 | using System.Reflection; | 32 | using System.Reflection; |
32 | using System.Text; | 33 | using System.Text; |
33 | using System.Text.RegularExpressions; | 34 | using System.Text.RegularExpressions; |
35 | using System.Threading; | ||
34 | using log4net; | 36 | using log4net; |
35 | using log4net.Appender; | 37 | using log4net.Appender; |
36 | using log4net.Core; | 38 | using log4net.Core; |
37 | using log4net.Repository; | 39 | using log4net.Repository; |
38 | using Nini.Config; | 40 | using Nini.Config; |
39 | using OpenSim.Framework.Console; | 41 | using OpenSim.Framework.Console; |
42 | using OpenSim.Framework.Monitoring; | ||
40 | 43 | ||
41 | namespace OpenSim.Framework.Servers | 44 | namespace OpenSim.Framework.Servers |
42 | { | 45 | { |
@@ -211,6 +214,22 @@ namespace OpenSim.Framework.Servers | |||
211 | "Run a command script from file", HandleScript); | 214 | "Run a command script from file", HandleScript); |
212 | 215 | ||
213 | m_console.Commands.AddCommand( | 216 | m_console.Commands.AddCommand( |
217 | "General", false, "show threads", | ||
218 | "show threads", | ||
219 | "Show thread status", HandleShow); | ||
220 | |||
221 | m_console.Commands.AddCommand( | ||
222 | "General", false, "threads abort", | ||
223 | "threads abort <thread-id>", | ||
224 | "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort); | ||
225 | |||
226 | m_console.Commands.AddCommand( | ||
227 | "General", false, "threads show", | ||
228 | "threads show", | ||
229 | "Show thread status. Synonym for \"show threads\"", | ||
230 | (string module, string[] args) => Notice(GetThreadsReport())); | ||
231 | |||
232 | m_console.Commands.AddCommand( | ||
214 | "General", false, "force gc", | 233 | "General", false, "force gc", |
215 | "force gc", | 234 | "force gc", |
216 | "Manually invoke runtime garbage collection. For debugging purposes", | 235 | "Manually invoke runtime garbage collection. For debugging purposes", |
@@ -244,6 +263,10 @@ namespace OpenSim.Framework.Servers | |||
244 | case "uptime": | 263 | case "uptime": |
245 | Notice(GetUptimeReport()); | 264 | Notice(GetUptimeReport()); |
246 | break; | 265 | break; |
266 | |||
267 | case "threads": | ||
268 | Notice(GetThreadsReport()); | ||
269 | break; | ||
247 | } | 270 | } |
248 | } | 271 | } |
249 | 272 | ||
@@ -556,6 +579,75 @@ namespace OpenSim.Framework.Servers | |||
556 | } | 579 | } |
557 | 580 | ||
558 | /// <summary> | 581 | /// <summary> |
582 | /// Get a report about the registered threads in this server. | ||
583 | /// </summary> | ||
584 | protected string GetThreadsReport() | ||
585 | { | ||
586 | // This should be a constant field. | ||
587 | string reportFormat = "{0,6} {1,35} {2,16} {3,13} {4,10} {5,30}"; | ||
588 | |||
589 | StringBuilder sb = new StringBuilder(); | ||
590 | Watchdog.ThreadWatchdogInfo[] threads = Watchdog.GetThreadsInfo(); | ||
591 | |||
592 | sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine); | ||
593 | |||
594 | int timeNow = Environment.TickCount & Int32.MaxValue; | ||
595 | |||
596 | sb.AppendFormat(reportFormat, "ID", "NAME", "LAST UPDATE (MS)", "LIFETIME (MS)", "PRIORITY", "STATE"); | ||
597 | sb.Append(Environment.NewLine); | ||
598 | |||
599 | foreach (Watchdog.ThreadWatchdogInfo twi in threads) | ||
600 | { | ||
601 | Thread t = twi.Thread; | ||
602 | |||
603 | sb.AppendFormat( | ||
604 | reportFormat, | ||
605 | t.ManagedThreadId, | ||
606 | t.Name, | ||
607 | timeNow - twi.LastTick, | ||
608 | timeNow - twi.FirstTick, | ||
609 | t.Priority, | ||
610 | t.ThreadState); | ||
611 | |||
612 | sb.Append("\n"); | ||
613 | } | ||
614 | |||
615 | sb.Append("\n"); | ||
616 | |||
617 | // For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting | ||
618 | // zero active threads. | ||
619 | int totalThreads = Process.GetCurrentProcess().Threads.Count; | ||
620 | if (totalThreads > 0) | ||
621 | sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); | ||
622 | |||
623 | sb.Append("Main threadpool (excluding script engine pools)\n"); | ||
624 | sb.Append(Util.GetThreadPoolReport()); | ||
625 | |||
626 | return sb.ToString(); | ||
627 | } | ||
628 | |||
629 | public virtual void HandleThreadsAbort(string module, string[] cmd) | ||
630 | { | ||
631 | if (cmd.Length != 3) | ||
632 | { | ||
633 | MainConsole.Instance.Output("Usage: threads abort <thread-id>"); | ||
634 | return; | ||
635 | } | ||
636 | |||
637 | int threadId; | ||
638 | if (!int.TryParse(cmd[2], out threadId)) | ||
639 | { | ||
640 | MainConsole.Instance.Output("ERROR: Thread id must be an integer"); | ||
641 | return; | ||
642 | } | ||
643 | |||
644 | if (Watchdog.AbortThread(threadId)) | ||
645 | MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId); | ||
646 | else | ||
647 | MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId); | ||
648 | } | ||
649 | |||
650 | /// <summary> | ||
559 | /// Console output is only possible if a console has been established. | 651 | /// Console output is only possible if a console has been established. |
560 | /// That is something that cannot be determined within this class. So | 652 | /// That is something that cannot be determined within this class. So |
561 | /// all attempts to use the console MUST be verified. | 653 | /// 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 | |||
1741 | StringBuilder sb = new StringBuilder(); | 1741 | StringBuilder sb = new StringBuilder(); |
1742 | if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) | 1742 | if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) |
1743 | { | 1743 | { |
1744 | threadPoolUsed = "SmartThreadPool"; | 1744 | // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool. |
1745 | maxThreads = m_ThreadPool.MaxThreads; | 1745 | if (m_ThreadPool != null) |
1746 | minThreads = m_ThreadPool.MinThreads; | 1746 | { |
1747 | inUseThreads = m_ThreadPool.InUseThreads; | 1747 | threadPoolUsed = "SmartThreadPool"; |
1748 | allocatedThreads = m_ThreadPool.ActiveThreads; | 1748 | maxThreads = m_ThreadPool.MaxThreads; |
1749 | waitingCallbacks = m_ThreadPool.WaitingCallbacks; | 1749 | minThreads = m_ThreadPool.MinThreads; |
1750 | inUseThreads = m_ThreadPool.InUseThreads; | ||
1751 | allocatedThreads = m_ThreadPool.ActiveThreads; | ||
1752 | waitingCallbacks = m_ThreadPool.WaitingCallbacks; | ||
1753 | } | ||
1750 | } | 1754 | } |
1751 | else if ( | 1755 | else if ( |
1752 | FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem | 1756 | FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem |