aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs5
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs8
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs6
-rw-r--r--OpenSim/Framework/Watchdog.cs183
-rw-r--r--OpenSim/Grid/UserServer.Modules/MessageServersConnector.cs8
-rw-r--r--OpenSim/Region/Application/OpenSim.cs11
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs19
-rw-r--r--OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs15
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs13
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs20
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs10
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs7
-rw-r--r--OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs12
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs83
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs8
17 files changed, 306 insertions, 120 deletions
diff --git a/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs b/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs
index ba9c653..63381a4 100644
--- a/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs
+++ b/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs
@@ -85,10 +85,7 @@ namespace OpenSim.Client.MXP.PacketHandler
85 85
86 m_transmitter = new Transmitter(port); 86 m_transmitter = new Transmitter(port);
87 87
88 m_clientThread = new Thread(StartListener); 88 StartListener();
89 m_clientThread.Name = "MXPThread";
90 m_clientThread.IsBackground = true;
91 m_clientThread.Start();
92 } 89 }
93 90
94 public void StartListener() 91 public void StartListener()
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 85d7be2..bec5ed3 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -1559,15 +1559,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1559 public void Start() 1559 public void Start()
1560 { 1560 {
1561 m_log.Info("[HTTPD]: Starting up HTTP Server"); 1561 m_log.Info("[HTTPD]: Starting up HTTP Server");
1562
1563 //m_workerThread = new Thread(new ThreadStart(StartHTTP));
1564 //m_workerThread.Name = "HttpThread";
1565 //m_workerThread.IsBackground = true;
1566 //m_workerThread.Start();
1567 //ThreadTracker.Add(m_workerThread);
1568 StartHTTP(); 1562 StartHTTP();
1569
1570
1571 } 1563 }
1572 1564
1573 private void StartHTTP() 1565 private void StartHTTP()
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index 1c54581..e7a64f7 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -50,9 +50,7 @@ namespace OpenSim.Framework.Servers.HttpServer
50 m_WorkerThreadCount = pWorkerThreadCount; 50 m_WorkerThreadCount = pWorkerThreadCount;
51 m_workerThreads = new Thread[m_WorkerThreadCount]; 51 m_workerThreads = new Thread[m_WorkerThreadCount];
52 m_PollServiceWorkerThreads = new PollServiceWorkerThread[m_WorkerThreadCount]; 52 m_PollServiceWorkerThreads = new PollServiceWorkerThread[m_WorkerThreadCount];
53 m_watcherThread = new Thread(ThreadStart);
54 53
55
56 //startup worker threads 54 //startup worker threads
57 for (uint i=0;i<m_WorkerThreadCount;i++) 55 for (uint i=0;i<m_WorkerThreadCount;i++)
58 { 56 {
@@ -65,11 +63,11 @@ namespace OpenSim.Framework.Servers.HttpServer
65 m_workerThreads[i].Start(); 63 m_workerThreads[i].Start();
66 64
67 } 65 }
66
68 //start watcher threads 67 //start watcher threads
68 m_watcherThread = new Thread(ThreadStart);
69 m_watcherThread.Name = "PollServiceWatcherThread"; 69 m_watcherThread.Name = "PollServiceWatcherThread";
70 m_watcherThread.Start(); 70 m_watcherThread.Start();
71
72
73 } 71 }
74 72
75 internal void ReQueueEvent(PollServiceHttpRequest req) 73 internal void ReQueueEvent(PollServiceHttpRequest req)
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}
diff --git a/OpenSim/Grid/UserServer.Modules/MessageServersConnector.cs b/OpenSim/Grid/UserServer.Modules/MessageServersConnector.cs
index 8ce353c..f24cef6 100644
--- a/OpenSim/Grid/UserServer.Modules/MessageServersConnector.cs
+++ b/OpenSim/Grid/UserServer.Modules/MessageServersConnector.cs
@@ -78,8 +78,6 @@ namespace OpenSim.Grid.UserServer.Modules
78 private OpenSim.Framework.BlockingQueue<PresenceNotification> m_NotifyQueue = 78 private OpenSim.Framework.BlockingQueue<PresenceNotification> m_NotifyQueue =
79 new OpenSim.Framework.BlockingQueue<PresenceNotification>(); 79 new OpenSim.Framework.BlockingQueue<PresenceNotification>();
80 80
81 Thread m_NotifyThread;
82
83 private IGridServiceCore m_core; 81 private IGridServiceCore m_core;
84 82
85 public event AgentLocationDelegate OnAgentLocation; 83 public event AgentLocationDelegate OnAgentLocation;
@@ -96,8 +94,8 @@ namespace OpenSim.Grid.UserServer.Modules
96 { 94 {
97 m_core = core; 95 m_core = core;
98 m_core.RegisterInterface<MessageServersConnector>(this); 96 m_core.RegisterInterface<MessageServersConnector>(this);
99 m_NotifyThread = new Thread(new ThreadStart(NotifyQueueRunner)); 97
100 m_NotifyThread.Start(); 98 Watchdog.StartThread(NotifyQueueRunner, "NotifyQueueRunner", ThreadPriority.Normal, true);
101 } 99 }
102 100
103 public void PostInitialise() 101 public void PostInitialise()
@@ -427,6 +425,8 @@ namespace OpenSim.Grid.UserServer.Modules
427 { 425 {
428 TellMessageServersAboutUserLogoffInternal(presence.agentID); 426 TellMessageServersAboutUserLogoffInternal(presence.agentID);
429 } 427 }
428
429 Watchdog.UpdateThread();
430 } 430 }
431 } 431 }
432 432
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 26298e7..0366d94 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -172,6 +172,9 @@ namespace OpenSim
172 m_scriptTimer.Elapsed += RunAutoTimerScript; 172 m_scriptTimer.Elapsed += RunAutoTimerScript;
173 } 173 }
174 174
175 // Hook up to the watchdog timer
176 Watchdog.OnWatchdogTimeout += WatchdogTimeoutHandler;
177
175 PrintFileToConsole("startuplogo.txt"); 178 PrintFileToConsole("startuplogo.txt");
176 179
177 // For now, start at the 'root' level by default 180 // For now, start at the 'root' level by default
@@ -384,6 +387,14 @@ namespace OpenSim
384 } 387 }
385 } 388 }
386 389
390 private void WatchdogTimeoutHandler(System.Threading.Thread thread, int lastTick)
391 {
392 int now = Environment.TickCount & Int32.MaxValue;
393
394 m_log.ErrorFormat("[WATCHDOG]: Timeout detected for thread \"{0}\". ThreadState={1}. Last tick was {2}ms ago",
395 thread.Name, thread.ThreadState, now - lastTick);
396 }
397
387 #region Console Commands 398 #region Console Commands
388 399
389 /// <summary> 400 /// <summary>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index a9f4b2c..734471e 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -187,14 +187,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
187 187
188 base.Start(m_recvBufferSize, m_asyncPacketHandling); 188 base.Start(m_recvBufferSize, m_asyncPacketHandling);
189 189
190 // Start the incoming packet processing thread 190 // Start the packet processing threads
191 Thread incomingThread = new Thread(IncomingPacketHandler); 191 Watchdog.StartThread(IncomingPacketHandler, "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false);
192 incomingThread.Name = "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")"; 192 Watchdog.StartThread(OutgoingPacketHandler, "Outgoing Packets (" + m_scene.RegionInfo.RegionName + ")", ThreadPriority.Normal, false);
193 incomingThread.Start();
194
195 Thread outgoingThread = new Thread(OutgoingPacketHandler);
196 outgoingThread.Name = "Outgoing Packets (" + m_scene.RegionInfo.RegionName + ")";
197 outgoingThread.Start();
198 } 193 }
199 194
200 public new void Stop() 195 public new void Stop()
@@ -775,11 +770,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
775 { 770 {
776 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex); 771 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex);
777 } 772 }
773
774 Watchdog.UpdateThread();
778 } 775 }
779 776
780 if (packetInbox.Count > 0) 777 if (packetInbox.Count > 0)
781 m_log.Warn("[LLUDPSERVER]: IncomingPacketHandler is shutting down, dropping " + packetInbox.Count + " packets"); 778 m_log.Warn("[LLUDPSERVER]: IncomingPacketHandler is shutting down, dropping " + packetInbox.Count + " packets");
782 packetInbox.Clear(); 779 packetInbox.Clear();
780
781 Watchdog.RemoveThread();
783 } 782 }
784 783
785 private void OutgoingPacketHandler() 784 private void OutgoingPacketHandler()
@@ -842,12 +841,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
842 // token bucket could get more tokens 841 // token bucket could get more tokens
843 if (!m_packetSent) 842 if (!m_packetSent)
844 Thread.Sleep((int)TickCountResolution); 843 Thread.Sleep((int)TickCountResolution);
844
845 Watchdog.UpdateThread();
845 } 846 }
846 catch (Exception ex) 847 catch (Exception ex)
847 { 848 {
848 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex); 849 m_log.Error("[LLUDPSERVER]: OutgoingPacketHandler loop threw an exception: " + ex.Message, ex);
849 } 850 }
850 } 851 }
852
853 Watchdog.RemoveThread();
851 } 854 }
852 855
853 private void ClientOutgoingPacketHandler(IClientAPI client) 856 private void ClientOutgoingPacketHandler(IClientAPI client)
diff --git a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
index d636b1c..62500a2 100644
--- a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
+++ b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
@@ -1208,10 +1208,7 @@ namespace OpenSim.Region.CoreModules.InterGrid
1208 if (homeScene.TryGetAvatar(avatarId,out avatar)) 1208 if (homeScene.TryGetAvatar(avatarId,out avatar))
1209 { 1209 {
1210 KillAUser ku = new KillAUser(avatar,mod); 1210 KillAUser ku = new KillAUser(avatar,mod);
1211 Thread ta = new Thread(ku.ShutdownNoLogout); 1211 Watchdog.StartThread(ku.ShutdownNoLogout, "OGPShutdown", ThreadPriority.Normal, true);
1212 ta.IsBackground = true;
1213 ta.Name = "ShutdownThread";
1214 ta.Start();
1215 } 1212 }
1216 } 1213 }
1217 1214
@@ -1261,7 +1258,13 @@ namespace OpenSim.Region.CoreModules.InterGrid
1261 1258
1262 avToBeKilled.ControllingClient.SendLogoutPacketWhenClosing = false; 1259 avToBeKilled.ControllingClient.SendLogoutPacketWhenClosing = false;
1263 1260
1264 Thread.Sleep(30000); 1261 int sleepMS = 30000;
1262 while (sleepMS > 0)
1263 {
1264 Watchdog.UpdateThread();
1265 Thread.Sleep(1000);
1266 sleepMS -= 1000;
1267 }
1265 1268
1266 // test for child agent because they might have come back 1269 // test for child agent because they might have come back
1267 if (avToBeKilled.IsChildAgent) 1270 if (avToBeKilled.IsChildAgent)
@@ -1270,6 +1273,8 @@ namespace OpenSim.Region.CoreModules.InterGrid
1270 avToBeKilled.ControllingClient.Close(); 1273 avToBeKilled.ControllingClient.Close();
1271 } 1274 }
1272 } 1275 }
1276
1277 Watchdog.RemoveThread();
1273 } 1278 }
1274 1279
1275 } 1280 }
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index fe9c8d9..c9fce91 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -128,7 +128,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
128 if (m_repliesRequired == 0) 128 if (m_repliesRequired == 0)
129 { 129 {
130 m_requestState = RequestState.Completed; 130 m_requestState = RequestState.Completed;
131 PerformAssetsRequestCallback(); 131 PerformAssetsRequestCallback(null);
132 return; 132 return;
133 } 133 }
134 134
@@ -246,9 +246,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
246 246
247 // We want to stop using the asset cache thread asap 247 // We want to stop using the asset cache thread asap
248 // as we now need to do the work of producing the rest of the archive 248 // as we now need to do the work of producing the rest of the archive
249 Thread newThread = new Thread(PerformAssetsRequestCallback); 249 Util.FireAndForget(PerformAssetsRequestCallback);
250 newThread.Name = "OpenSimulator archiving thread post assets receipt";
251 newThread.Start();
252 } 250 }
253 else 251 else
254 { 252 {
@@ -265,7 +263,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
265 /// <summary> 263 /// <summary>
266 /// Perform the callback on the original requester of the assets 264 /// Perform the callback on the original requester of the assets
267 /// </summary> 265 /// </summary>
268 protected void PerformAssetsRequestCallback() 266 protected void PerformAssetsRequestCallback(object o)
269 { 267 {
270 try 268 try
271 { 269 {
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index 4e40084..a4bcbad 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -74,7 +74,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
74 private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>(); 74 private Dictionary<ulong, int> m_blacklistedregions = new Dictionary<ulong, int>();
75 private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>(); 75 private Dictionary<ulong, string> m_cachedRegionMapItemsAddress = new Dictionary<ulong, string>();
76 private List<UUID> m_rootAgents = new List<UUID>(); 76 private List<UUID> m_rootAgents = new List<UUID>();
77 private Thread mapItemReqThread;
78 private volatile bool threadrunning = false; 77 private volatile bool threadrunning = false;
79 78
80 //private int CacheRegionsDistance = 256; 79 //private int CacheRegionsDistance = 256;
@@ -338,13 +337,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
338 { 337 {
339 if (threadrunning) return; 338 if (threadrunning) return;
340 threadrunning = true; 339 threadrunning = true;
340
341 m_log.Debug("[WORLD MAP]: Starting remote MapItem request thread"); 341 m_log.Debug("[WORLD MAP]: Starting remote MapItem request thread");
342 mapItemReqThread = new Thread(new ThreadStart(process)); 342
343 mapItemReqThread.IsBackground = true; 343 Watchdog.StartThread(process, "MapItemRequestThread", ThreadPriority.BelowNormal, true);
344 mapItemReqThread.Name = "MapItemRequestThread";
345 mapItemReqThread.Priority = ThreadPriority.BelowNormal;
346 mapItemReqThread.SetApartmentState(ApartmentState.MTA);
347 mapItemReqThread.Start();
348 } 344 }
349 345
350 /// <summary> 346 /// <summary>
@@ -461,6 +457,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
461 OSDMap response = RequestMapItemsAsync("", st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle); 457 OSDMap response = RequestMapItemsAsync("", st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle);
462 RequestMapItemsCompleted(response); 458 RequestMapItemsCompleted(response);
463 } 459 }
460
461 Watchdog.UpdateThread();
464 } 462 }
465 } 463 }
466 catch (Exception e) 464 catch (Exception e)
@@ -469,6 +467,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
469 } 467 }
470 468
471 threadrunning = false; 469 threadrunning = false;
470 Watchdog.RemoveThread();
472 } 471 }
473 472
474 /// <summary> 473 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 5005ac9..4b87f92 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -81,8 +81,6 @@ namespace OpenSim.Region.Framework.Scenes
81 81
82 protected Timer m_restartWaitTimer = new Timer(); 82 protected Timer m_restartWaitTimer = new Timer();
83 83
84 protected Thread m_updateEntitiesThread;
85
86 public SimStatsReporter StatsReporter; 84 public SimStatsReporter StatsReporter;
87 85
88 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 86 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
@@ -945,11 +943,8 @@ namespace OpenSim.Region.Framework.Scenes
945 HeartbeatThread = null; 943 HeartbeatThread = null;
946 } 944 }
947 m_lastUpdate = Environment.TickCount; 945 m_lastUpdate = Environment.TickCount;
948 HeartbeatThread = new Thread(new ParameterizedThreadStart(Heartbeat)); 946
949 HeartbeatThread.SetApartmentState(ApartmentState.MTA); 947 HeartbeatThread = Watchdog.StartThread(Heartbeat, "Heartbeat for region " + RegionInfo.RegionName, ThreadPriority.Normal, false);
950 HeartbeatThread.Name = string.Format("Heartbeat for region {0}", RegionInfo.RegionName);
951 HeartbeatThread.Priority = ThreadPriority.AboveNormal;
952 HeartbeatThread.Start();
953 } 948 }
954 949
955 /// <summary> 950 /// <summary>
@@ -976,12 +971,13 @@ namespace OpenSim.Region.Framework.Scenes
976 /// <summary> 971 /// <summary>
977 /// Performs per-frame updates regularly 972 /// Performs per-frame updates regularly
978 /// </summary> 973 /// </summary>
979 /// <param name="sender"></param> 974 private void Heartbeat()
980 /// <param name="e"></param>
981 private void Heartbeat(object sender)
982 { 975 {
983 if (!Monitor.TryEnter(m_heartbeatLock)) 976 if (!Monitor.TryEnter(m_heartbeatLock))
977 {
978 Watchdog.RemoveThread();
984 return; 979 return;
980 }
985 981
986 try 982 try
987 { 983 {
@@ -998,6 +994,8 @@ namespace OpenSim.Region.Framework.Scenes
998 Monitor.Pulse(m_heartbeatLock); 994 Monitor.Pulse(m_heartbeatLock);
999 Monitor.Exit(m_heartbeatLock); 995 Monitor.Exit(m_heartbeatLock);
1000 } 996 }
997
998 Watchdog.RemoveThread();
1001 } 999 }
1002 1000
1003 /// <summary> 1001 /// <summary>
@@ -1146,6 +1144,8 @@ namespace OpenSim.Region.Framework.Scenes
1146 1144
1147 if ((maintc < (m_timespan * 1000)) && maintc > 0) 1145 if ((maintc < (m_timespan * 1000)) && maintc > 0)
1148 Thread.Sleep(maintc); 1146 Thread.Sleep(maintc);
1147
1148 Watchdog.UpdateThread();
1149 } 1149 }
1150 } 1150 }
1151 1151
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index df03b8d..4b0d01a 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -67,9 +67,8 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
67 { 67 {
68 m_client = client; 68 m_client = client;
69 m_scene = scene; 69 m_scene = scene;
70 70
71 Thread loopThread = new Thread(InternalLoop); 71 Watchdog.StartThread(InternalLoop, "IRCClientView", ThreadPriority.Normal, false);
72 loopThread.Start();
73 } 72 }
74 73
75 private void SendServerCommand(string command) 74 private void SendServerCommand(string command)
@@ -102,7 +101,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
102 { 101 {
103 try 102 try
104 { 103 {
105 string strbuf = ""; 104 string strbuf = String.Empty;
106 105
107 while (m_connected && m_client.Connected) 106 while (m_connected && m_client.Connected)
108 { 107 {
@@ -140,6 +139,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
140 } 139 }
141 140
142 Thread.Sleep(0); 141 Thread.Sleep(0);
142 Watchdog.UpdateThread();
143 } 143 }
144 } 144 }
145 catch (IOException) 145 catch (IOException)
@@ -156,6 +156,8 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
156 156
157 m_log.Warn("[IRCd] Disconnected client."); 157 m_log.Warn("[IRCd] Disconnected client.");
158 } 158 }
159
160 Watchdog.RemoveThread();
159 } 161 }
160 162
161 private void ProcessInMessage(string message, string command) 163 private void ProcessInMessage(string message, string command)
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs
index 91ce9f1..eb39026 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs
@@ -33,6 +33,7 @@ using System.Reflection;
33using System.Text; 33using System.Text;
34using System.Threading; 34using System.Threading;
35using log4net; 35using log4net;
36using OpenSim.Framework;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
37 38
38namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server 39namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
@@ -56,8 +57,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
56 57
57 m_listener.Start(50); 58 m_listener.Start(50);
58 59
59 Thread thread = new Thread(ListenLoop); 60 Watchdog.StartThread(ListenLoop, "IRCServer", ThreadPriority.Normal, false);
60 thread.Start();
61 m_baseScene = baseScene; 61 m_baseScene = baseScene;
62 } 62 }
63 63
@@ -72,7 +72,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
72 while (m_running) 72 while (m_running)
73 { 73 {
74 AcceptClient(m_listener.AcceptTcpClient()); 74 AcceptClient(m_listener.AcceptTcpClient());
75 Watchdog.UpdateThread();
75 } 76 }
77
78 Watchdog.RemoveThread();
76 } 79 }
77 80
78 private void AcceptClient(TcpClient client) 81 private void AcceptClient(TcpClient client)
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs
index 16fe9e9..8d6c41d 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs
@@ -86,7 +86,6 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
86 /// </value> 86 /// </value>
87 Hashtable m_sceneList = Hashtable.Synchronized(new Hashtable()); 87 Hashtable m_sceneList = Hashtable.Synchronized(new Hashtable());
88 State m_state = State.NONE; 88 State m_state = State.NONE;
89 Thread m_thread = null;
90 CMView m_view = null; 89 CMView m_view = null;
91 90
92 #endregion Fields 91 #endregion Fields
@@ -148,10 +147,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
148 lock (this) 147 lock (this)
149 { 148 {
150 m_estateModule = scene.RequestModuleInterface<IEstateModule>(); 149 m_estateModule = scene.RequestModuleInterface<IEstateModule>();
151 m_thread = new Thread(MainLoop); 150 Watchdog.StartThread(MainLoop, "Content Management", ThreadPriority.Normal, true);
152 m_thread.Name = "Content Management";
153 m_thread.IsBackground = true;
154 m_thread.Start();
155 m_state = State.NONE; 151 m_state = State.NONE;
156 } 152 }
157 } 153 }
@@ -200,6 +196,8 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
200 m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- uuuuuuuuuh, what?"); 196 m_log.Debug("[CONTENT MANAGEMENT] MAIN LOOP -- uuuuuuuuuh, what?");
201 break; 197 break;
202 } 198 }
199
200 Watchdog.UpdateThread();
203 } 201 }
204 } 202 }
205 catch (Exception e) 203 catch (Exception e)
@@ -209,6 +207,8 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
209 "[CONTENT MANAGEMENT]: Content management thread terminating with exception. PLEASE REBOOT YOUR SIM - CONTENT MANAGEMENT WILL NOT BE AVAILABLE UNTIL YOU DO. Exception is {0}", 207 "[CONTENT MANAGEMENT]: Content management thread terminating with exception. PLEASE REBOOT YOUR SIM - CONTENT MANAGEMENT WILL NOT BE AVAILABLE UNTIL YOU DO. Exception is {0}",
210 e); 208 e);
211 } 209 }
210
211 Watchdog.RemoveThread();
212 } 212 }
213 213
214 /// <summary> 214 /// <summary>
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs
index 583d2ff..51fd41a 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs
@@ -132,12 +132,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
132 /// </summary> 132 /// </summary>
133 private void Start() 133 private void Start()
134 { 134 {
135 EventQueueThread = new Thread(EventQueueThreadLoop); 135 EventQueueThread = Watchdog.StartThread(EventQueueThreadLoop, "EventQueueManagerThread_" + ThreadCount, MyThreadPriority, true);
136 EventQueueThread.IsBackground = true;
137
138 EventQueueThread.Priority = MyThreadPriority;
139 EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount;
140 EventQueueThread.Start();
141 136
142 // Look at this... Don't you wish everyone did that solid 137 // Look at this... Don't you wish everyone did that solid
143 // coding everywhere? :P 138 // coding everywhere? :P
@@ -184,6 +179,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
184 while (true) 179 while (true)
185 { 180 {
186 DoProcessQueue(); 181 DoProcessQueue();
182 Watchdog.UpdateThread();
187 } 183 }
188 } 184 }
189 catch (ThreadAbortException) 185 catch (ThreadAbortException)
@@ -214,6 +210,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
214 m_log.ErrorFormat("[{0}]: Exception {1} thrown", ScriptEngineName, e.GetType().ToString()); 210 m_log.ErrorFormat("[{0}]: Exception {1} thrown", ScriptEngineName, e.GetType().ToString());
215 throw e; 211 throw e;
216 } 212 }
213
214 Watchdog.UpdateThread();
217 } 215 }
218 } 216 }
219 catch (ThreadAbortException) 217 catch (ThreadAbortException)
@@ -226,6 +224,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
226 "[{0}]: Event queue thread terminating with exception. PLEASE REBOOT YOUR SIM - SCRIPT EVENTS WILL NOT WORK UNTIL YOU DO. Exception is {1}", 224 "[{0}]: Event queue thread terminating with exception. PLEASE REBOOT YOUR SIM - SCRIPT EVENTS WILL NOT WORK UNTIL YOU DO. Exception is {1}",
227 ScriptEngineName, e); 225 ScriptEngineName, e);
228 } 226 }
227
228 Watchdog.RemoveThread();
229 } 229 }
230 230
231 public void DoProcessQueue() 231 public void DoProcessQueue()
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs
index 7ffdb1a..87fdf1f 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs
@@ -93,10 +93,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
93 { 93 {
94 if (MaintenanceThreadThread == null) 94 if (MaintenanceThreadThread == null)
95 { 95 {
96 MaintenanceThreadThread = new Thread(MaintenanceLoop); 96 MaintenanceThreadThread = Watchdog.StartThread(MaintenanceLoop, "ScriptMaintenanceThread", ThreadPriority.Normal, true);
97 MaintenanceThreadThread.Name = "ScriptMaintenanceThread";
98 MaintenanceThreadThread.IsBackground = true;
99 MaintenanceThreadThread.Start();
100 } 97 }
101 } 98 }
102 99
@@ -164,56 +161,54 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
164 MaintenanceLoopTicks_ScriptLoadUnload_Count++; 161 MaintenanceLoopTicks_ScriptLoadUnload_Count++;
165 MaintenanceLoopTicks_Other_Count++; 162 MaintenanceLoopTicks_Other_Count++;
166 163
167 164 foreach (ScriptEngine m_ScriptEngine in new ArrayList(ScriptEngine.ScriptEngines))
168 //lock (ScriptEngine.ScriptEngines) 165 {
169 //{ 166 // lastScriptEngine = m_ScriptEngine;
170 foreach (ScriptEngine m_ScriptEngine in new ArrayList(ScriptEngine.ScriptEngines)) 167 // Re-reading config every x seconds
168 if (MaintenanceLoopTicks_Other_Count >= MaintenanceLoopTicks_Other)
171 { 169 {
172 // lastScriptEngine = m_ScriptEngine; 170 MaintenanceLoopTicks_Other_ResetCount = true;
173 // Re-reading config every x seconds 171 if (m_ScriptEngine.RefreshConfigFilens > 0)
174 if (MaintenanceLoopTicks_Other_Count >= MaintenanceLoopTicks_Other)
175 { 172 {
176 MaintenanceLoopTicks_Other_ResetCount = true; 173 // Check if its time to re-read config
177 if (m_ScriptEngine.RefreshConfigFilens > 0) 174 if (DateTime.Now.Ticks - Last_ReReadConfigFilens >
175 m_ScriptEngine.RefreshConfigFilens)
178 { 176 {
179 // Check if its time to re-read config 177 //m_log.Debug("Time passed: " + (DateTime.Now.Ticks - Last_ReReadConfigFilens) + ">" + m_ScriptEngine.RefreshConfigFilens);
180 if (DateTime.Now.Ticks - Last_ReReadConfigFilens > 178 // Its time to re-read config file
181 m_ScriptEngine.RefreshConfigFilens) 179 m_ScriptEngine.ReadConfig();
182 { 180 Last_ReReadConfigFilens = DateTime.Now.Ticks; // Reset time
183 //m_log.Debug("Time passed: " + (DateTime.Now.Ticks - Last_ReReadConfigFilens) + ">" + m_ScriptEngine.RefreshConfigFilens); 181 }
184 // Its time to re-read config file
185 m_ScriptEngine.ReadConfig();
186 Last_ReReadConfigFilens = DateTime.Now.Ticks; // Reset time
187 }
188 182
189 183
190 // Adjust number of running script threads if not correct 184 // Adjust number of running script threads if not correct
191 if (m_ScriptEngine.m_EventQueueManager != null) 185 if (m_ScriptEngine.m_EventQueueManager != null)
192 m_ScriptEngine.m_EventQueueManager.AdjustNumberOfScriptThreads(); 186 m_ScriptEngine.m_EventQueueManager.AdjustNumberOfScriptThreads();
193 187
194 // Check if any script has exceeded its max execution time 188 // Check if any script has exceeded its max execution time
195 if (EventQueueManager.EnforceMaxExecutionTime) 189 if (EventQueueManager.EnforceMaxExecutionTime)
190 {
191 // We are enforcing execution time
192 if (DateTime.Now.Ticks - Last_maxFunctionExecutionTimens >
193 EventQueueManager.maxFunctionExecutionTimens)
196 { 194 {
197 // We are enforcing execution time 195 // Its time to check again
198 if (DateTime.Now.Ticks - Last_maxFunctionExecutionTimens > 196 m_ScriptEngine.m_EventQueueManager.CheckScriptMaxExecTime(); // Do check
199 EventQueueManager.maxFunctionExecutionTimens) 197 Last_maxFunctionExecutionTimens = DateTime.Now.Ticks; // Reset time
200 {
201 // Its time to check again
202 m_ScriptEngine.m_EventQueueManager.CheckScriptMaxExecTime(); // Do check
203 Last_maxFunctionExecutionTimens = DateTime.Now.Ticks; // Reset time
204 }
205 } 198 }
206 } 199 }
207 } 200 }
208 if (MaintenanceLoopTicks_ScriptLoadUnload_Count >= MaintenanceLoopTicks_ScriptLoadUnload)
209 {
210 MaintenanceLoopTicks_ScriptLoadUnload_ResetCount = true;
211 // LOAD / UNLOAD SCRIPTS
212 if (m_ScriptEngine.m_ScriptManager != null)
213 m_ScriptEngine.m_ScriptManager.DoScriptLoadUnload();
214 }
215 } 201 }
216 //} 202 if (MaintenanceLoopTicks_ScriptLoadUnload_Count >= MaintenanceLoopTicks_ScriptLoadUnload)
203 {
204 MaintenanceLoopTicks_ScriptLoadUnload_ResetCount = true;
205 // LOAD / UNLOAD SCRIPTS
206 if (m_ScriptEngine.m_ScriptManager != null)
207 m_ScriptEngine.m_ScriptManager.DoScriptLoadUnload();
208 }
209 }
210
211 Watchdog.UpdateThread();
217 } 212 }
218 } 213 }
219 catch(ThreadAbortException) 214 catch(ThreadAbortException)
@@ -225,6 +220,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
225 m_log.ErrorFormat("Exception in MaintenanceLoopThread. Thread will recover after 5 sec throttle. Exception: {0}", ex.ToString()); 220 m_log.ErrorFormat("Exception in MaintenanceLoopThread. Thread will recover after 5 sec throttle. Exception: {0}", ex.ToString());
226 } 221 }
227 } 222 }
223
224 Watchdog.RemoveThread();
228 } 225 }
229 #endregion 226 #endregion
230 227
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index 1607d34..9d97cb2 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -137,11 +137,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
137 if (cmdHandlerThread == null) 137 if (cmdHandlerThread == null)
138 { 138 {
139 // Start the thread that will be doing the work 139 // Start the thread that will be doing the work
140 cmdHandlerThread = new Thread(CmdHandlerThreadLoop); 140 cmdHandlerThread = Watchdog.StartThread(CmdHandlerThreadLoop, "AsyncLSLCmdHandlerThread", ThreadPriority.Normal, true);
141 cmdHandlerThread.Name = "AsyncLSLCmdHandlerThread";
142 cmdHandlerThread.Priority = ThreadPriority.BelowNormal;
143 cmdHandlerThread.IsBackground = true;
144 cmdHandlerThread.Start();
145 } 141 }
146 } 142 }
147 143
@@ -185,6 +181,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
185 Thread.Sleep(cmdHandlerThreadCycleSleepms); 181 Thread.Sleep(cmdHandlerThreadCycleSleepms);
186 182
187 DoOneCmdHandlerPass(); 183 DoOneCmdHandlerPass();
184
185 Watchdog.UpdateThread();
188 } 186 }
189 } 187 }
190 catch 188 catch