/// <summary> /// Check watched threads. Fire alarm if appropriate. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) { int now = Environment.TickCount & Int32.MaxValue; int msElapsed = now - LastWatchdogThreadTick; if (msElapsed > WATCHDOG_INTERVAL_MS * 2) { m_log.WarnFormat( "[WATCHDOG]: {0} ms since Watchdog last ran. Interval should be approximately {1} ms", msElapsed, WATCHDOG_INTERVAL_MS); } LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue; Action <ThreadWatchdogInfo> callback = OnWatchdogTimeout; if (callback != null) { List <ThreadWatchdogInfo> callbackInfos = null; lock (m_threads) { // get a copy since we may change m_threads List <ThreadWatchdogInfo> threadsInfo = m_threads.Values.ToList(); foreach (ThreadWatchdogInfo threadInfo in threadsInfo) { if (threadInfo.Thread.ThreadState == ThreadState.Stopped) { RemoveThread(threadInfo.Thread.ManagedThreadId); if (callbackInfos == null) { callbackInfos = new List <ThreadWatchdogInfo>(); } callbackInfos.Add(threadInfo); } else if (!threadInfo.IsTimedOut && now - threadInfo.LastTick >= threadInfo.Timeout) { threadInfo.IsTimedOut = true; if (threadInfo.AlarmIfTimeout) { if (callbackInfos == null) { callbackInfos = new List <ThreadWatchdogInfo>(); } // Send a copy of the watchdog info to prevent race conditions where the watchdog // thread updates the monitoring info after an alarm has been sent out. callbackInfos.Add(new ThreadWatchdogInfo(threadInfo)); } } } } if (callbackInfos != null) { foreach (ThreadWatchdogInfo callbackInfo in callbackInfos) { callback(callbackInfo); } } } if (MemoryWatchdog.Enabled) { MemoryWatchdog.Update(); } ChecksManager.CheckChecks(); StatsManager.RecordStats(); m_watchdogTimer.Start(); }
/// <summary> /// Check watched threads. Fire alarm if appropriate. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void WatchdogTimerElapsed(object sender) { if (!m_enabled) { return; } int now = Environment.TickCount & Int32.MaxValue; int msElapsed = now - LastWatchdogThreadTick; if (msElapsed > WATCHDOG_INTERVAL_MS * 2) { m_log.WarnFormat( "[WATCHDOG]: {0} ms since Watchdog last ran. Interval should be approximately {1} ms", msElapsed, WATCHDOG_INTERVAL_MS); } LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue; Action <ThreadWatchdogInfo> callback = OnWatchdogTimeout; if (callback != null) { List <ThreadWatchdogInfo> callbackInfos = null; List <ThreadWatchdogInfo> threadsToRemove = null; const ThreadState thgone = ThreadState.Stopped; lock (m_threads) { foreach (ThreadWatchdogInfo threadInfo in m_threads.Values) { if (!m_enabled) { return; } if ((threadInfo.Thread.ThreadState & thgone) != 0) { if (threadsToRemove == null) { threadsToRemove = new List <ThreadWatchdogInfo>(); } threadsToRemove.Add(threadInfo); /* * if(callbackInfos == null) * callbackInfos = new List<ThreadWatchdogInfo>(); * * callbackInfos.Add(threadInfo); */ } else if (!threadInfo.IsTimedOut && now - threadInfo.LastTick >= threadInfo.Timeout) { threadInfo.IsTimedOut = true; if (threadInfo.AlarmIfTimeout) { if (callbackInfos == null) { callbackInfos = new List <ThreadWatchdogInfo>(); } // Send a copy of the watchdog info to prevent race conditions where the watchdog // thread updates the monitoring info after an alarm has been sent out. callbackInfos.Add(new ThreadWatchdogInfo(threadInfo)); } } } if (threadsToRemove != null) { foreach (ThreadWatchdogInfo twi in threadsToRemove) { RemoveThread(twi.Thread.ManagedThreadId); } } } if (callbackInfos != null) { foreach (ThreadWatchdogInfo callbackInfo in callbackInfos) { callback(callbackInfo); } } } if (MemoryWatchdog.Enabled) { MemoryWatchdog.Update(); } ChecksManager.CheckChecks(); StatsManager.RecordStats(); m_watchdogTimer.Change(WATCHDOG_INTERVAL_MS, Timeout.Infinite); }