aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Watchdog.cs
diff options
context:
space:
mode:
authorJohn Hurliman2009-10-22 12:33:23 -0700
committerJohn Hurliman2009-10-22 12:33:23 -0700
commitb2ed348aa2746fbf034b713d006e40366c479d5a (patch)
tree26c114e88f54e64e1fdf17dcc7de1e54165db2bc /OpenSim/Framework/Watchdog.cs
parentMerge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff)
downloadopensim-SC_OLD-b2ed348aa2746fbf034b713d006e40366c479d5a.zip
opensim-SC_OLD-b2ed348aa2746fbf034b713d006e40366c479d5a.tar.gz
opensim-SC_OLD-b2ed348aa2746fbf034b713d006e40366c479d5a.tar.bz2
opensim-SC_OLD-b2ed348aa2746fbf034b713d006e40366c479d5a.tar.xz
Implemented a Watchdog class. Do not manually create Thread objects anymore, use Watchdog.StartThread(). While your thread is running call Watchdog.UpdateThread(). When it is shutting down call Watchdog.RemoveThread(). Most of the threads in OpenSim have been updated
Diffstat (limited to 'OpenSim/Framework/Watchdog.cs')
-rw-r--r--OpenSim/Framework/Watchdog.cs183
1 files changed, 183 insertions, 0 deletions
diff --git a/OpenSim/Framework/Watchdog.cs b/OpenSim/Framework/Watchdog.cs
new file mode 100644
index 0000000..b905609
--- /dev/null
+++ b/OpenSim/Framework/Watchdog.cs
@@ -0,0 +1,183 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Threading;
31
32namespace OpenSim.Framework
33{
34 /// <summary>
35 /// Manages launching threads and keeping watch over them for timeouts
36 /// </summary>
37 public static class Watchdog
38 {
39 /// <summary>Timer interval in milliseconds for the watchdog timer</summary>
40 const double WATCHDOG_INTERVAL_MS = 2500.0d;
41 /// <summary>Maximum timeout in milliseconds before a thread is considered dead</summary>
42 const int WATCHDOG_TIMEOUT_MS = 5000;
43
44 [System.Diagnostics.DebuggerDisplay("{Thread.Name}")]
45 private class ThreadWatchdogInfo
46 {
47 public Thread Thread;
48 public int LastTick;
49
50 public ThreadWatchdogInfo(Thread thread)
51 {
52 Thread = thread;
53 LastTick = Environment.TickCount & Int32.MaxValue;
54 }
55 }
56
57 /// <summary>
58 /// This event is called whenever a tracked thread is stopped or
59 /// has not called UpdateThread() in time
60 /// </summary>
61 /// <param name="thread">The thread that has been identified as dead</param>
62 /// <param name="lastTick">The last time this thread called UpdateThread()</param>
63 public delegate void WatchdogTimeout(Thread thread, int lastTick);
64
65 /// <summary>This event is called whenever a tracked thread is
66 /// stopped or has not called UpdateThread() in time</summary>
67 public static event WatchdogTimeout OnWatchdogTimeout;
68
69 private static Dictionary<int, ThreadWatchdogInfo> m_threads;
70 private static System.Timers.Timer m_watchdogTimer;
71
72 static Watchdog()
73 {
74 m_threads = new Dictionary<int, ThreadWatchdogInfo>();
75 m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS);
76 m_watchdogTimer.AutoReset = false;
77 m_watchdogTimer.Elapsed += WatchdogTimerElapsed;
78 m_watchdogTimer.Start();
79 }
80
81 /// <summary>
82 /// Start a new thread that is tracked by the watchdog timer
83 /// </summary>
84 /// <param name="start">The method that will be executed in a new thread</param>
85 /// <param name="name">A name to give to the new thread</param>
86 /// <param name="priority">Priority to run the thread at</param>
87 /// <param name="isBackground">True to run this thread as a background
88 /// thread, otherwise false</param>
89 /// <returns>The newly created Thread object</returns>
90 public static Thread StartThread(ThreadStart start, string name, ThreadPriority priority, bool isBackground)
91 {
92 Thread thread = new Thread(start);
93 thread.Name = name;
94 thread.Priority = priority;
95 thread.IsBackground = isBackground;
96 thread.Start();
97
98 lock (m_threads)
99 m_threads.Add(thread.ManagedThreadId, new ThreadWatchdogInfo(thread));
100
101 return thread;
102 }
103
104 /// <summary>
105 /// Marks the current thread as alive
106 /// </summary>
107 public static void UpdateThread()
108 {
109 UpdateThread(Thread.CurrentThread.ManagedThreadId);
110 }
111
112 /// <summary>
113 /// Marks a thread as alive
114 /// </summary>
115 /// <param name="threadID">The ManagedThreadId of the thread to mark as
116 /// alive</param>
117 public static void UpdateThread(int threadID)
118 {
119 ThreadWatchdogInfo threadInfo;
120
121 lock (m_threads)
122 {
123 if (m_threads.TryGetValue(threadID, out threadInfo))
124 {
125 threadInfo.LastTick = Environment.TickCount & Int32.MaxValue;
126 }
127 }
128 }
129
130 /// <summary>
131 /// Stops watchdog tracking on the current thread
132 /// </summary>
133 /// <returns>True if the thread was removed from the list of tracked
134 /// threads, otherwise false</returns>
135 public static bool RemoveThread()
136 {
137 return RemoveThread(Thread.CurrentThread.ManagedThreadId);
138 }
139
140 /// <summary>
141 /// Stops watchdog tracking on a thread
142 /// </summary>
143 /// <param name="threadID">The ManagedThreadId of the thread to stop
144 /// tracking</param>
145 /// <returns>True if the thread was removed from the list of tracked
146 /// threads, otherwise false</returns>
147 public static bool RemoveThread(int threadID)
148 {
149 lock (m_threads)
150 return m_threads.Remove(threadID);
151 }
152
153 private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
154 {
155 WatchdogTimeout callback = OnWatchdogTimeout;
156
157 if (callback != null)
158 {
159 ThreadWatchdogInfo timedOut = null;
160
161 lock (m_threads)
162 {
163 int now = Environment.TickCount;
164
165 foreach (ThreadWatchdogInfo threadInfo in m_threads.Values)
166 {
167 if (threadInfo.Thread.ThreadState == ThreadState.Stopped || now - threadInfo.LastTick >= WATCHDOG_TIMEOUT_MS)
168 {
169 timedOut = threadInfo;
170 m_threads.Remove(threadInfo.Thread.ManagedThreadId);
171 break;
172 }
173 }
174 }
175
176 if (timedOut != null)
177 callback(timedOut.Thread, timedOut.LastTick);
178 }
179
180 m_watchdogTimer.Start();
181 }
182 }
183}