#!/usr/bin/python # -*- coding: utf-8 -*- # # Copyright (C) 2003-2009 Edgewall Software # Copyright (C) 2003-2004 Jonas Borgström # All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://trac.edgewall.org/wiki/TracLicense. # # This software consists of voluntary contributions made by many # individuals. For the exact contribution history, see the revision # history and logs, available at http://trac.edgewall.org/log/. # # Author: Jonas Borgström from trac.web._fcgi import WSGIServer from trac.web._fcgi import Connection from trac.web.main import dispatch_request import threading import time import gc import os import signal _proc_status = '/proc/%d/status' % os.getpid() _scale = {'kB': 1024.0, 'mB': 1024.0*1024.0, 'KB': 1024.0, 'MB': 1024.0*1024.0} def _VmB(VmKey): '''Private. ''' global _proc_status, _scale # get pseudo file /proc//status try: t = open(_proc_status) v = t.read() t.close() except: return 0.0 # non-Linux? # get VmKey line e.g. 'VmRSS: 9999 kB\n ...' i = v.index(VmKey) v = v[i:].split(None, 3) # whitespace if len(v) < 3: return 0.0 # invalid format? # convert Vm value to bytes return float(v[1]) * _scale[v[2]] def memory(since=0.0): '''Return memory usage in bytes. ''' return _VmB('VmSize:') - since def resident(since=0.0): '''Return resident memory usage in bytes. ''' return _VmB('VmRSS:') - since def stacksize(since=0.0): '''Return stack size in bytes. ''' return _VmB('VmStk:') - since connectionCount = 0 connectionLock = threading.Lock() class CountConnection(Connection): def __init__(self, sock, addr, server): global connectionCount connectionLock.acquire() connectionCount = connectionCount+1 connectionLock.release() super(CountConnection, self).__init__(sock, addr, server) def run(self): global connectionCount super(CountConnection, self).run() connectionLock.acquire() connectionCount = connectionCount-1 connectionLock.release() class GCWSGIServer(WSGIServer): def __init__(self, application, **kw): super(GCWSGIServer, self).__init__(application, **kw) self._connectionClass = CountConnection self.loopCount = 0 def _mainloopPeriodic(self): global connectionCount if(self.loopCount == 100): self.loopCount = 0 else: self.loopCount = self.loopCount + 1 if(self.loopCount == 100 and resident() > 1024*1024*90): os.kill(os.getppid(), signal.SIGUSR1) # print 'count is ', connectionCount # time.sleep(1) start = time.time() while(connectionCount > 0 and time.time() < start + 30): time.sleep(0.01) # print 'count is ', connectionCount # print 'waiting on:' # for t in threading.enumerate(): # print 'thread: ', t.getName() # main_thread = threading.currentThread() # for t in threading.enumerate(): # print 'thread: ' # print t.getName() # if t is not main_thread: # try: # t.join() # except: # pass self._keepGoing = False #gc.collect() #self.loopCount=0 # print 'done exiting' # def _restoreSignalHandlers(self): # print 'restore' # super(GCWSGIServer, self)._restoreSignalHandlers() # def _cleanupSocket(self, sock): # print 'cleanup' # super(GCWSGIServer, self)._cleanupSocket(sock) try: import os import pkg_resources if 'TRAC_ENV' not in os.environ and \ 'TRAC_ENV_PARENT_DIR' not in os.environ: os.environ['TRAC_ENV'] = '/var/trac/perian' if 'PYTHON_EGG_CACHE' not in os.environ: if 'TRAC_ENV' in os.environ: egg_cache = os.path.join(os.environ['TRAC_ENV'], '.egg-cache') elif 'TRAC_ENV_PARENT_DIR' in os.environ: egg_cache = os.path.join(os.environ['TRAC_ENV_PARENT_DIR'], '.egg-cache') pkg_resources.set_extraction_path(egg_cache) from trac.web import fcgi_frontend # fcgi_frontend.run() params = {}; GCWSGIServer(dispatch_request, **params).run() # print 'done' except SystemExit: raise except Exception, e: print 'Content-Type: text/plain\r\n\r\n', print 'Oops...' print print 'Trac detected an internal error:' print print e print import traceback import StringIO tb = StringIO.StringIO() traceback.print_exc(file=tb) print tb.getvalue()