commit c4454e05284d36fb6ecafc9c2f33c7b0a9ffab43 Author: Damian Johnson atagar@torproject.org Date: Wed Apr 27 21:46:21 2011 -0700
fix: Stacktrace from unjoined thread at shutdown
There's a rare (but repeated) stack trace due to an unjoined thread at shutdown: Exception in thread Thread-3 (most likely raised during interpreter shutdown): Traceback (most recent call last): File "/usr/lib/python2.6/threading.py", line 525, in __bootstrap_inner File "/home/atagar/Desktop/arm/src/util/sysTools.py", line 542, in run File "/usr/lib/python2.6/threading.py", line 135, in release <type 'exceptions.TypeError'>: 'NoneType' object is not callable
This isn't harmful, but it is annoying. This change is attempting to be extra careful that all resourceTracker threads have been joined, and that the controller is stopped beforehand (preventing stray BW events from triggering additional queries).
The stacktrace _seems_ to be more commonly caused by long-running arm processes, but I don't have a reliable repro case. --- src/cli/controller.py | 13 ++++++------- src/cli/graphing/resourceStats.py | 4 ++-- src/util/sysTools.py | 21 ++++----------------- 3 files changed, 12 insertions(+), 26 deletions(-)
diff --git a/src/cli/controller.py b/src/cli/controller.py index 22d1772..8543ccb 100644 --- a/src/cli/controller.py +++ b/src/cli/controller.py @@ -825,20 +825,19 @@ def drawTorMonitor(stdscr, startTime, loggedEvents, isBlindMode): panels["conn"].join() panels["log"].join()
- # joins on utility daemon threads - this might take a moment since - # the internal threadpools being joined might be sleeping conn = torTools.getConn() - myPid = conn.getMyPid() + conn.close() # joins on TorCtl event thread
- resourceTracker = sysTools.getResourceTracker(myPid) if (myPid and sysTools.isTrackerAlive(myPid)) else None + # joins on utility daemon threads - this might take a moment since + # the internal threadpools being joined might be sleeping + resourceTrackers = sysTools.RESOURCE_TRACKERS.values() resolver = connections.getResolver("tor") if connections.isResolverAlive("tor") else None - if resourceTracker: resourceTracker.stop() + for tracker in resourceTrackers: tracker.stop() if resolver: resolver.stop() # sets halt flag (returning immediately) hostnames.stop() # halts and joins on hostname worker thread pool - if resourceTracker: resourceTracker.join() + for tracker in resourceTrackers: tracker.join() if resolver: resolver.join() # joins on halted resolver
- conn.close() # joins on TorCtl event thread break elif key == curses.KEY_LEFT or key == curses.KEY_RIGHT: # switch page diff --git a/src/cli/graphing/resourceStats.py b/src/cli/graphing/resourceStats.py index f26d5c1..a9a8aee 100644 --- a/src/cli/graphing/resourceStats.py +++ b/src/cli/graphing/resourceStats.py @@ -36,9 +36,9 @@ class ResourceStats(graphPanel.GraphStats):
primary, secondary = 0, 0 if self.queryPid: - resourceTracker = sysTools.getResourceTracker(self.queryPid) + resourceTracker = sysTools.getResourceTracker(self.queryPid, True)
- if not resourceTracker.lastQueryFailed(): + if resourceTracker and not resourceTracker.lastQueryFailed(): primary, _, secondary, _ = resourceTracker.getResourceUsage() primary *= 100 # decimal percentage to whole numbers secondary /= 1048576 # translate size to MB so axis labels are short diff --git a/src/util/sysTools.py b/src/util/sysTools.py index 8d95733..2775194 100644 --- a/src/util/sysTools.py +++ b/src/util/sysTools.py @@ -347,27 +347,13 @@ def call(command, cacheAge=0, suppressExc=False, quiet=True):
return results
-def isTrackerAlive(pid): - """ - Provides true if a running, singleton instance exists for the given pid, - false otherwise. - - Arguments: - pid - pid of the process being tracked - """ - - if pid in RESOURCE_TRACKERS: - if RESOURCE_TRACKERS[pid].isAlive(): return True - else: del RESOURCE_TRACKERS[pid] - - return False - -def getResourceTracker(pid): +def getResourceTracker(pid, noSpawn = False): """ Provides a running singleton ResourceTracker instance for the given pid.
Arguments: - pid - pid of the process being tracked + pid - pid of the process being tracked + noSpawn - returns None rather than generating a singleton instance if True """
if pid in RESOURCE_TRACKERS: @@ -375,6 +361,7 @@ def getResourceTracker(pid): if tracker.isAlive(): return tracker else: del RESOURCE_TRACKERS[pid]
+ if noSpawn: return None tracker = ResourceTracker(pid, CONFIG["queries.resourceUsage.rate"]) RESOURCE_TRACKERS[pid] = tracker tracker.start()
tor-commits@lists.torproject.org