def getThreadDebugLog(s, thread): if s.debugmessages.has_key(thread): message = "\nLast %d debug messages logged for %s prior to exception:\n"\ % (len(s.debugmessages[thread]), thread.getName()) message += "\n".join(s.debugmessages[thread]) else: message = "\nNo debug messages were logged for %s." % \ thread.getName() return message
def _registerThread(self, thread): "Called by thread classes when a thread is created." assert(isinstance(thread, ManagedThread)) self._listLock.acquire() try: assert(not thread.getName() in self._activeThreads) debug(Debug, "Registering " + thread.getName() + " thread") self._activeThreads[thread.getName()] = thread debug(Debug, self.summary()) finally: self._listLock.release()
def _registerThread(self, thread): "Called by thread classes when a thread is created." assert (isinstance(thread, ManagedThread)) self._listLock.acquire() try: assert (not thread.getName() in self._activeThreads) debug(Debug, "Registering " + thread.getName() + " thread") self._activeThreads[thread.getName()] = thread debug(Debug, self.summary()) finally: self._listLock.release()
def active_threads(self): """Returns an iterator over all current stack frames for all active threads in the process. The result for each is a tuple consisting of the thread identifier, a categorisation of the type of thread, and the stack frame. Note that we actually treat any greenlets as threads as well. In that case the thread ID is the id() of the greenlet. This is in this class for convenience as needs to access the currently active transactions to categorise transaction threads as being for web transactions or background tasks. """ # TODO 返回活线程信息 # First yield up those for real Python threads. # TODO 返回一个字典,将每个线程的标识符映射到调用该函数时该线程中当前活动的最顶层堆栈帧 for thread_id, frame in sys._current_frames().items(): trace = self._cache.get(thread_id) transaction = trace and trace.transaction if transaction is not None: if transaction.background_task: # TODO 如果是后台队列任务,非Web事物 yield transaction, thread_id, 'BACKGROUND', frame else: yield transaction, thread_id, 'REQUEST', frame # TODO Web事物 else: # Note that there may not always be a thread object. # This is because thread could have been created direct # against the thread module rather than via the high # level threading module. Categorise anything we can't # obtain a name for as being 'OTHER'. thread = threading._active.get(thread_id) if thread is not None and thread.getName().startswith('NR-'): yield None, thread_id, 'AGENT', frame else: yield None, thread_id, 'OTHER', frame # Now yield up those corresponding to greenlets. Right now only # doing this for greenlets in which any active transactions are # running. We don't have a way of knowing what non transaction # threads are running. debug = global_settings().debug # TODO 启用协程分析 if debug.enable_coroutine_profiling: for thread_id, trace in self._cache.items(): transaction = trace.transaction if transaction and transaction._greenlet is not None: gr = transaction._greenlet( ) # TODO !!!!!!这一块要弄懂,还是要仔细了解下greenlet框架 if gr and gr.gr_frame is not None: if transaction.background_task: yield (transaction, thread_id, 'BACKGROUND', gr.gr_frame) else: yield (transaction, thread_id, 'REQUEST', gr.gr_frame)
def unstartedThreads(self): self._listLock.acquire() try: ret = [] for thread in self._activeThreads.values(): if not thread.getName() in self._startedThreads: ret.append(thread) return ret finally: self._listLock.release()
def active_threads(self): """Returns an iterator over all current stack frames for all active threads in the process. The result for each is a tuple consisting of the thread identifier, a categorisation of the type of thread, and the stack frame. Note that we actually treat any greenlets as threads as well. In that case the thread ID is the id() of the greenlet. This is in this class for convenience as needs to access the currently active transactions to categorise transaction threads as being for web transactions or background tasks. """ # First yield up those for real Python threads. for thread_id, frame in sys._current_frames().items(): transaction = self._cache.get(thread_id) if transaction is not None: if transaction.background_task: yield transaction, thread_id, 'BACKGROUND', frame else: yield transaction, thread_id, 'REQUEST', frame else: # Note that there may not always be a thread object. # This is because thread could have been created direct # against the thread module rather than via the high # level threading module. Categorise anything we can't # obtain a name for as being 'OTHER'. thread = threading._active.get(thread_id) if thread is not None and thread.getName().startswith('NR-'): yield None, thread_id, 'AGENT', frame else: yield None, thread_id, 'OTHER', frame # Now yield up those corresponding to greenlets. Right now only # doing this for greenlets in which any active transactions are # running. We don't have a way of knowing what non transaction # threads are running. debug = global_settings().debug if debug.enable_coroutine_profiling: for thread_id, transaction in self._cache.items(): if transaction._greenlet is not None: gr = transaction._greenlet() if gr and gr.gr_frame is not None: if transaction.background_task: yield (transaction, thread_id, 'BACKGROUND', gr.gr_frame) else: yield (transaction, thread_id, 'REQUEST', gr.gr_frame)
def runningThreads(self): self._listLock.acquire() try: ret = [] for thread in self._startedThreads.values(): if not thread.getName() in [ te[0].getName() for te in self._threadTerminations]: ret.append(thread) return ret finally: self._listLock.release()
def runningThreads(self): self._listLock.acquire() try: ret = [] for thread in self._startedThreads.values(): if not thread.getName() in [ te[0].getName() for te in self._threadTerminations ]: ret.append(thread) return ret finally: self._listLock.release()
def store_exception(exc_info=None, thread=None): if exc_info == None: exc_info = sys.exc_info() if thread == None: thread = threading.currentThread() name = thread.getName() info = "" if hasattr(thread, 'threadinfo'): info = thread.threadinfo desc = "%s (%s)" % (name, info) maxtracebacks = 10 CrashStore.exceptions.append((exc_info, time.time(), desc), ) while len(CrashStore.exceptions) > maxtracebacks: CrashStore.exceptions.pop(0)
def store_exception(exc_info=None, thread=None): if exc_info == None: exc_info = sys.exc_info() if thread == None: thread = threading.currentThread() name = thread.getName() info = "" if hasattr(thread, 'threadinfo'): info = thread.threadinfo desc = "%s (%s)" % (name, info) maxtracebacks = 10 CrashStore.exceptions.append((exc_info, time.time(), desc),) while len(CrashStore.exceptions) > maxtracebacks: CrashStore.exceptions.pop(0)
def threadException(s, thread): print s.getThreadExceptionString(thread) s._printData('threadException', "%s\n%s" % \ (thread.getName(), s.getThreadExceptionString(thread))) s.delThreadDebugLog(thread) s.terminate(100)
def getThreadExceptionString(s, thread): message = "Thread '%s' terminated with exception:\n%s" % \ (thread.getName(), thread.getExitStackTrace()) message += "\n" + s.getThreadDebugLog(thread) return message
class ThreadManager(object): """Singleton class for managing active python threads.""" def __init__(self): self._activeThreads = {} self._startedThreads = {} self._threadTerminations = [] self._pidErrors = 0 # Protects the three lists above self._listLock = threading.RLock() self._threadTerminationQueue = Queue.Queue() debug(Debug, self.summary()) def _registerThread(self, thread): "Called by thread classes when a thread is created." assert (isinstance(thread, ManagedThread)) self._listLock.acquire() try: assert (not thread.getName() in self._activeThreads) debug(Debug, "Registering " + thread.getName() + " thread") self._activeThreads[thread.getName()] = thread debug(Debug, self.summary()) finally: self._listLock.release() def _registerThreadStart(self, thread): "Called by the thread classes' run method." assert (isinstance(thread, ManagedThread)) self._listLock.acquire() try: assert (thread.getName() in self._activeThreads) assert (not thread.getName() in self._startedThreads) debug(Debug, "Registering " + thread.getName() + " thread start") self._startedThreads[thread.getName()] = thread debug(Debug, self.summary()) finally: self._listLock.release() def _registerResult(self, thread, exceptionInfo): self._threadTerminationQueue.put((thread.getName(), exceptionInfo)) def runningThreads(self): self._listLock.acquire() try: ret = [] for thread in self._startedThreads.values(): if not thread.getName() in [ te[0].getName() for te in self._threadTerminations ]: ret.append(thread) return ret finally: self._listLock.release() def unstartedThreads(self): self._listLock.acquire() try: ret = [] for thread in self._activeThreads.values(): if not thread.getName() in self._startedThreads: ret.append(thread) return ret finally: self._listLock.release() def numThreadsLeft(self): return len(self.unfinishedThreads()) def unfinishedThreads(self): "Return created threads that have not terminated." self._listLock.acquire() try: return self._activeThreads.values() finally: self._listLock.release() def waitAll(self, timeout=3600, mourningTime=5): "Wait for all threads to terminate." debug(MajorEvent, "Waiting for all test threads to terminate") debug(MinorEvent, self.summary()) limit = time.time() + timeout while self.numThreadsLeft() > 0: try: nextTimeout = limit - time.time() if nextTimeout <= 0: raise chakana.error.Timeout(self.unfinishedThreads()[0], timeout) else: self.waitOne(nextTimeout) except chakana.error.Timeout, err: debug( Error, "Timeout waiting for " + err.child.getName() + " thread, killing subprocesses.") self.killAll() while self.numThreadsLeft() > 0: try: self.waitOne(mourningTime) except chakana.error.Timeout: debug(Error, "Timeout while mourning threads, aborting") signal.signal(signal.SIGABRT, signal.SIG_DFL) os.abort() raise debug( MinorEvent, "Done waiting for " + str(len(self._startedThreads)) + " threads") debug(Debug, self.summary()) for (thread, excInfo) in self._threadTerminations: if not excInfo is None: debug( MinorEvent, "Rethrowing exception from " + thread.getName() + " thread") raise chakana.error.ChildException(excInfo[1], excInfo)
def threadExited(s, thread): s._printData('threadExited', thread.getName()) UIBase.threadExited(s, thread)
def unregisterthread(s, thread): UIBase.unregisterthread(s, thread) s._printData('unregisterthread', thread.getName())
def _registerResult(self, thread, exceptionInfo): self._threadTerminationQueue.put((thread.getName(), exceptionInfo))