Package elisa :: Package plugins :: Package good :: Package testing :: Module threads_monitor
[hide private]
[frames] | no frames]

Source Code for Module elisa.plugins.good.testing.threads_monitor

  1  # -*- coding: utf-8 -*- 
  2  # Elisa - Home multimedia server 
  3  # Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com). 
  4  # All rights reserved. 
  5  # 
  6  # This file is available under one of two license agreements. 
  7  # 
  8  # This file is licensed under the GPL version 3. 
  9  # See "LICENSE.GPL" in the root of this distribution including a special 
 10  # exception to use Elisa with Fluendo's plugins. 
 11  # 
 12  # The GPL part of Elisa is also available under a commercial licensing 
 13  # agreement from Fluendo. 
 14  # See "LICENSE.Elisa" in the root directory of this distribution package 
 15  # for details on that license. 
 16   
 17  """ 
 18  Threads monitoring service 
 19  """ 
 20   
 21  __maintainer__ = "Florian Boucault <florian@fluendo.com>" 
 22   
 23  import os, sys 
 24  import tempfile 
 25  import traceback 
 26  import threading 
 27   
 28  from elisa.base_components import service_provider 
 29   
 30  from twisted.internet import reactor 
 31   
32 -class ThreadsMonitor(service_provider.ServiceProvider):
33 """ 34 Service checking periodically the current number of threads 35 and giving a warning if a certain limit is reached. 36 37 Warning: this component only takes into account threads created from 38 Python 39 """ 40 41 default_config = {'max_threads': '2', 42 'frequency': '1.0'} 43 config_doc = {'max_threads': 'Maximum number of threads at any time.', 44 'frequency': 'Frequency of the monitoring in times per' 45 ' second'} 46
47 - def initialize(self):
48 service_provider.ServiceProvider.initialize(self) 49 self._delayed = None
50
51 - def start(self):
52 self._max_threads = int(self.config.get('max_threads')) 53 self._frequency = float(self.config.get('frequency')) 54 self.info("Checking %s times per second that no more than %s threads \ 55 are concurrently running", self._frequency, self._max_threads) 56 57 self._delayed = reactor.callLater(1.0/self._frequency, self._check)
58
59 - def stop(self):
60 if self._delayed != None and self._delayed.active(): 61 reactor.cancelCallLater(self._delayed)
62
63 - def _check(self):
64 frames = sys._current_frames() 65 66 # does not take into account Twisted's idle threads 67 waiters_count = len(reactor.threadpool.waiters) 68 threads_count = len(frames) - waiters_count 69 70 if threads_count > self._max_threads: 71 fd_log, path = tempfile.mkstemp(prefix="elisa_", 72 suffix="_threads") 73 74 os.write(fd_log, "Stack of concurrent Python threads\n") 75 os.write(fd_log, "==================================\n\n") 76 77 for id, frame in frames.items(): 78 try: 79 thread = threading._active[id] 80 except KeyError: 81 # the thread died in the meantime 82 continue 83 84 # ignore Twisted's idle threads 85 if thread in reactor.threadpool.waiters: 86 continue 87 88 os.write(fd_log, "%s\n" % thread.getName()) 89 stack = traceback.format_stack(frame) 90 for line in stack: 91 os.write(fd_log, line) 92 os.write(fd_log, "\n") 93 94 self.warning("Too many concurrent threads (%s); stacks written at " 95 "%s" % (threads_count, path)) 96 os.close(fd_log) 97 98 self._delayed = reactor.callLater(1.0/self._frequency, self._check)
99