diff options
Diffstat (limited to 'OpenSim/Framework/Watchdog.cs')
-rw-r--r-- | OpenSim/Framework/Watchdog.cs | 102 |
1 files changed, 86 insertions, 16 deletions
diff --git a/OpenSim/Framework/Watchdog.cs b/OpenSim/Framework/Watchdog.cs index 3389ecb..952f039 100644 --- a/OpenSim/Framework/Watchdog.cs +++ b/OpenSim/Framework/Watchdog.cs | |||
@@ -40,19 +40,31 @@ namespace OpenSim.Framework | |||
40 | { | 40 | { |
41 | /// <summary>Timer interval in milliseconds for the watchdog timer</summary> | 41 | /// <summary>Timer interval in milliseconds for the watchdog timer</summary> |
42 | const double WATCHDOG_INTERVAL_MS = 2500.0d; | 42 | const double WATCHDOG_INTERVAL_MS = 2500.0d; |
43 | |||
43 | /// <summary>Maximum timeout in milliseconds before a thread is considered dead</summary> | 44 | /// <summary>Maximum timeout in milliseconds before a thread is considered dead</summary> |
44 | const int WATCHDOG_TIMEOUT_MS = 5000; | 45 | const int WATCHDOG_TIMEOUT_MS = 5000; |
45 | 46 | ||
46 | [System.Diagnostics.DebuggerDisplay("{Thread.Name}")] | 47 | [System.Diagnostics.DebuggerDisplay("{Thread.Name}")] |
47 | public class ThreadWatchdogInfo | 48 | public class ThreadWatchdogInfo |
48 | { | 49 | { |
49 | public Thread Thread; | 50 | public Thread Thread { get; private set; } |
50 | public int LastTick; | 51 | public int LastTick { get; set; } |
52 | |||
53 | /// <summary> | ||
54 | /// Number of milliseconds before we notify that the thread is having a problem. | ||
55 | /// </summary> | ||
56 | public int Timeout { get; set; } | ||
57 | |||
58 | /// <summary> | ||
59 | /// Is this thread considered timed out? | ||
60 | /// </summary> | ||
61 | public bool IsTimedOut { get; set; } | ||
51 | 62 | ||
52 | public ThreadWatchdogInfo(Thread thread) | 63 | public ThreadWatchdogInfo(Thread thread, int timeout) |
53 | { | 64 | { |
54 | Thread = thread; | 65 | Thread = thread; |
55 | LastTick = Environment.TickCount; | 66 | Timeout = timeout; |
67 | LastTick = Environment.TickCount & Int32.MaxValue; | ||
56 | } | 68 | } |
57 | } | 69 | } |
58 | 70 | ||
@@ -82,7 +94,7 @@ namespace OpenSim.Framework | |||
82 | } | 94 | } |
83 | 95 | ||
84 | /// <summary> | 96 | /// <summary> |
85 | /// Start a new thread that is tracked by the watchdog timer | 97 | /// Start a new thread that is tracked by the watchdog timer. |
86 | /// </summary> | 98 | /// </summary> |
87 | /// <param name="start">The method that will be executed in a new thread</param> | 99 | /// <param name="start">The method that will be executed in a new thread</param> |
88 | /// <param name="name">A name to give to the new thread</param> | 100 | /// <param name="name">A name to give to the new thread</param> |
@@ -92,12 +104,37 @@ namespace OpenSim.Framework | |||
92 | /// <returns>The newly created Thread object</returns> | 104 | /// <returns>The newly created Thread object</returns> |
93 | public static Thread StartThread(ThreadStart start, string name, ThreadPriority priority, bool isBackground) | 105 | public static Thread StartThread(ThreadStart start, string name, ThreadPriority priority, bool isBackground) |
94 | { | 106 | { |
107 | return StartThread(start, name, priority, isBackground, WATCHDOG_TIMEOUT_MS); | ||
108 | } | ||
109 | |||
110 | /// <summary> | ||
111 | /// Start a new thread that is tracked by the watchdog timer | ||
112 | /// </summary> | ||
113 | /// <param name="start">The method that will be executed in a new thread</param> | ||
114 | /// <param name="name">A name to give to the new thread</param> | ||
115 | /// <param name="priority">Priority to run the thread at</param> | ||
116 | /// <param name="isBackground">True to run this thread as a background | ||
117 | /// thread, otherwise false</param> | ||
118 | /// <param name="timeout"> | ||
119 | /// Number of milliseconds to wait until we issue a warning about timeout. | ||
120 | /// </para> | ||
121 | /// <returns>The newly created Thread object</returns> | ||
122 | public static Thread StartThread( | ||
123 | ThreadStart start, string name, ThreadPriority priority, bool isBackground, int timeout) | ||
124 | { | ||
95 | Thread thread = new Thread(start); | 125 | Thread thread = new Thread(start); |
96 | thread.Name = name; | 126 | thread.Name = name; |
97 | thread.Priority = priority; | 127 | thread.Priority = priority; |
98 | thread.IsBackground = isBackground; | 128 | thread.IsBackground = isBackground; |
99 | thread.Start(); | 129 | thread.Start(); |
100 | 130 | ||
131 | ThreadWatchdogInfo twi = new ThreadWatchdogInfo(thread, timeout); | ||
132 | |||
133 | m_log.Debug("[WATCHDOG]: Started tracking thread \"" + twi.Thread.Name + "\" (ID " + twi.Thread.ManagedThreadId + ")"); | ||
134 | |||
135 | lock (m_threads) | ||
136 | m_threads.Add(twi.Thread.ManagedThreadId, twi); | ||
137 | |||
101 | return thread; | 138 | return thread; |
102 | } | 139 | } |
103 | 140 | ||
@@ -112,25 +149,42 @@ namespace OpenSim.Framework | |||
112 | /// <summary> | 149 | /// <summary> |
113 | /// Stops watchdog tracking on the current thread | 150 | /// Stops watchdog tracking on the current thread |
114 | /// </summary> | 151 | /// </summary> |
115 | /// <returns>True if the thread was removed from the list of tracked | 152 | /// <returns> |
116 | /// threads, otherwise false</returns> | 153 | /// True if the thread was removed from the list of tracked |
154 | /// threads, otherwise false | ||
155 | /// </returns> | ||
117 | public static bool RemoveThread() | 156 | public static bool RemoveThread() |
118 | { | 157 | { |
119 | return RemoveThread(Thread.CurrentThread.ManagedThreadId); | 158 | return RemoveThread(Thread.CurrentThread.ManagedThreadId); |
120 | } | 159 | } |
121 | 160 | ||
122 | private static void AddThread(ThreadWatchdogInfo threadInfo) | 161 | private static bool RemoveThread(int threadID) |
123 | { | 162 | { |
124 | m_log.Debug("[WATCHDOG]: Started tracking thread \"" + threadInfo.Thread.Name + "\" (ID " + threadInfo.Thread.ManagedThreadId + ")"); | ||
125 | |||
126 | lock (m_threads) | 163 | lock (m_threads) |
127 | m_threads.Add(threadInfo.Thread.ManagedThreadId, threadInfo); | 164 | return m_threads.Remove(threadID); |
128 | } | 165 | } |
129 | 166 | ||
167 | <<<<<<< HEAD:OpenSim/Framework/Watchdog.cs | ||
130 | public static bool RemoveThread(int threadID) | 168 | public static bool RemoveThread(int threadID) |
169 | ======= | ||
170 | public static bool AbortThread(int threadID) | ||
171 | >>>>>>> master:OpenSim/Framework/Watchdog.cs | ||
131 | { | 172 | { |
132 | lock (m_threads) | 173 | lock (m_threads) |
133 | return m_threads.Remove(threadID); | 174 | { |
175 | if (m_threads.ContainsKey(threadID)) | ||
176 | { | ||
177 | ThreadWatchdogInfo twi = m_threads[threadID]; | ||
178 | twi.Thread.Abort(); | ||
179 | RemoveThread(threadID); | ||
180 | |||
181 | return true; | ||
182 | } | ||
183 | else | ||
184 | { | ||
185 | return false; | ||
186 | } | ||
187 | } | ||
134 | } | 188 | } |
135 | 189 | ||
136 | private static void UpdateThread(int threadID) | 190 | private static void UpdateThread(int threadID) |
@@ -144,9 +198,18 @@ namespace OpenSim.Framework | |||
144 | try | 198 | try |
145 | { | 199 | { |
146 | if (m_threads.TryGetValue(threadID, out threadInfo)) | 200 | if (m_threads.TryGetValue(threadID, out threadInfo)) |
201 | <<<<<<< HEAD:OpenSim/Framework/Watchdog.cs | ||
147 | threadInfo.LastTick = Environment.TickCount; | 202 | threadInfo.LastTick = Environment.TickCount; |
203 | ======= | ||
204 | { | ||
205 | threadInfo.LastTick = Environment.TickCount & Int32.MaxValue; | ||
206 | threadInfo.IsTimedOut = false; | ||
207 | } | ||
208 | >>>>>>> master:OpenSim/Framework/Watchdog.cs | ||
148 | else | 209 | else |
149 | AddThread(new ThreadWatchdogInfo(Thread.CurrentThread)); | 210 | { |
211 | m_log.WarnFormat("[WATCHDOG]: Asked to update thread {0} which is not being monitored", threadID); | ||
212 | } | ||
150 | } | 213 | } |
151 | catch { } | 214 | catch { } |
152 | } | 215 | } |
@@ -157,7 +220,8 @@ namespace OpenSim.Framework | |||
157 | /// <returns></returns> | 220 | /// <returns></returns> |
158 | public static ThreadWatchdogInfo[] GetThreads() | 221 | public static ThreadWatchdogInfo[] GetThreads() |
159 | { | 222 | { |
160 | return m_threads.Values.ToArray(); | 223 | lock (m_threads) |
224 | return m_threads.Values.ToArray(); | ||
161 | } | 225 | } |
162 | 226 | ||
163 | private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) | 227 | private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) |
@@ -174,10 +238,16 @@ namespace OpenSim.Framework | |||
174 | 238 | ||
175 | foreach (ThreadWatchdogInfo threadInfo in m_threads.Values) | 239 | foreach (ThreadWatchdogInfo threadInfo in m_threads.Values) |
176 | { | 240 | { |
177 | if (threadInfo.Thread.ThreadState == ThreadState.Stopped || now - threadInfo.LastTick >= WATCHDOG_TIMEOUT_MS) | 241 | if (threadInfo.Thread.ThreadState == ThreadState.Stopped) |
242 | { | ||
243 | timedOut = threadInfo; | ||
244 | RemoveThread(threadInfo.Thread.ManagedThreadId); | ||
245 | break; | ||
246 | } | ||
247 | else if (!threadInfo.IsTimedOut && now - threadInfo.LastTick >= threadInfo.Timeout) | ||
178 | { | 248 | { |
249 | threadInfo.IsTimedOut = true; | ||
179 | timedOut = threadInfo; | 250 | timedOut = threadInfo; |
180 | m_threads.Remove(threadInfo.Thread.ManagedThreadId); | ||
181 | break; | 251 | break; |
182 | } | 252 | } |
183 | } | 253 | } |