From 41f2f3132bdcbfb8020c7fd6e5f3b7e48c75b1cf Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Fri, 5 Sep 2014 23:20:59 +0100
Subject: For monitoring purposes, start non-timeout tasks (which do not
currently use a threadpool) via Watchdog.RunInThread() rather than
Util.RunThreadNoTimeout()
The functionality is the same but this allow us to monitor such tasks via "show threads" and abort them for test purposes, etc.
Also extends thread names to provide more info (e.g. SendInitialDataToClient says what client the task is for).
---
OpenSim/Framework/Monitoring/Watchdog.cs | 60 ++++++++++++++++++++++++++------
1 file changed, 49 insertions(+), 11 deletions(-)
(limited to 'OpenSim/Framework/Monitoring/Watchdog.cs')
diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs
index 427ed7b..e9e7bd2 100644
--- a/OpenSim/Framework/Monitoring/Watchdog.cs
+++ b/OpenSim/Framework/Monitoring/Watchdog.cs
@@ -187,15 +187,16 @@ namespace OpenSim.Framework.Monitoring
/// Priority to run the thread at
/// True to run this thread as a background thread, otherwise false
/// Trigger an alarm function is we have timed out
+ /// If true then creation of thread is logged.
/// The newly created Thread object
public static Thread StartThread(
- ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout)
+ ThreadStart start, string name, ThreadPriority priority, bool isBackground, bool alarmIfTimeout, bool log = true)
{
- return StartThread(start, name, priority, isBackground, alarmIfTimeout, null, DEFAULT_WATCHDOG_TIMEOUT_MS);
+ return StartThread(start, name, priority, isBackground, alarmIfTimeout, null, DEFAULT_WATCHDOG_TIMEOUT_MS, log);
}
///
- /// Start a new thread that is tracked by the watchdog timer
+ /// Start a new thread that is tracked by the watchdog
///
/// The method that will be executed in a new thread
/// A name to give to the new thread
@@ -208,10 +209,11 @@ namespace OpenSim.Framework.Monitoring
/// Normally, this will just return some useful debugging information.
///
/// Number of milliseconds to wait until we issue a warning about timeout.
+ /// If true then creation of thread is logged.
/// The newly created Thread object
public static Thread StartThread(
ThreadStart start, string name, ThreadPriority priority, bool isBackground,
- bool alarmIfTimeout, Func alarmMethod, int timeout)
+ bool alarmIfTimeout, Func alarmMethod, int timeout, bool log = true)
{
Thread thread = new Thread(start);
thread.Name = name;
@@ -222,8 +224,9 @@ namespace OpenSim.Framework.Monitoring
= new ThreadWatchdogInfo(thread, timeout)
{ AlarmIfTimeout = alarmIfTimeout, AlarmMethod = alarmMethod };
- m_log.DebugFormat(
- "[WATCHDOG]: Started tracking thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId);
+ if (log)
+ m_log.DebugFormat(
+ "[WATCHDOG]: Started tracking thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId);
lock (m_threads)
m_threads.Add(twi.Thread.ManagedThreadId, twi);
@@ -234,6 +237,39 @@ namespace OpenSim.Framework.Monitoring
}
///
+ /// Run the callback in a new thread immediately. If the thread exits with an exception log it but do
+ /// not propogate it.
+ ///
+ /// Code for the thread to execute.
+ /// Name of the thread
+ /// Object to pass to the thread.
+ public static void RunInThread(WaitCallback callback, string name, object obj, bool log = false)
+ {
+ if (Util.FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
+ {
+ Culture.SetCurrentCulture();
+ callback(obj);
+ return;
+ }
+
+ ThreadStart ts = new ThreadStart(delegate()
+ {
+ try
+ {
+ Culture.SetCurrentCulture();
+ callback(obj);
+ Watchdog.RemoveThread(log:false);
+ }
+ catch (Exception e)
+ {
+ m_log.Error(string.Format("[WATCHDOG]: Exception in thread {0}.", name), e);
+ }
+ });
+
+ StartThread(ts, name, ThreadPriority.Normal, true, false, log:log);
+ }
+
+ ///
/// Marks the current thread as alive
///
public static void UpdateThread()
@@ -244,24 +280,26 @@ namespace OpenSim.Framework.Monitoring
///
/// Stops watchdog tracking on the current thread
///
+ /// If true then normal events in thread removal are not logged.
///
/// True if the thread was removed from the list of tracked
/// threads, otherwise false
///
- public static bool RemoveThread()
+ public static bool RemoveThread(bool log = true)
{
- return RemoveThread(Thread.CurrentThread.ManagedThreadId);
+ return RemoveThread(Thread.CurrentThread.ManagedThreadId, log);
}
- private static bool RemoveThread(int threadID)
+ private static bool RemoveThread(int threadID, bool log = true)
{
lock (m_threads)
{
ThreadWatchdogInfo twi;
if (m_threads.TryGetValue(threadID, out twi))
{
- m_log.DebugFormat(
- "[WATCHDOG]: Removing thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId);
+ if (log)
+ m_log.DebugFormat(
+ "[WATCHDOG]: Removing thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId);
twi.Cleanup();
m_threads.Remove(threadID);
--
cgit v1.1