1
0
mirror of https://github.com/djohnlewis/stackdump synced 2025-12-07 00:13:33 +00:00

Upgraded Bottle.py to 0.10.11 and CherryPy to 3.2.2.

This commit is contained in:
Samuel Lai
2012-08-12 14:57:25 +10:00
parent 6156d69af0
commit dd24d98b39
31 changed files with 6622 additions and 3249 deletions

View File

@@ -453,13 +453,14 @@ class BackgroundTask(threading.Thread):
it won't delay stopping the whole process.
"""
def __init__(self, interval, function, args=[], kwargs={}):
def __init__(self, interval, function, args=[], kwargs={}, bus=None):
threading.Thread.__init__(self)
self.interval = interval
self.function = function
self.args = args
self.kwargs = kwargs
self.running = False
self.bus = bus
def cancel(self):
self.running = False
@@ -473,8 +474,9 @@ class BackgroundTask(threading.Thread):
try:
self.function(*self.args, **self.kwargs)
except Exception:
self.bus.log("Error in background task thread function %r." %
self.function, level=40, traceback=True)
if self.bus:
self.bus.log("Error in background task thread function %r."
% self.function, level=40, traceback=True)
# Quit on first error to avoid massive logs.
raise
@@ -506,8 +508,8 @@ class Monitor(SimplePlugin):
if self.frequency > 0:
threadname = self.name or self.__class__.__name__
if self.thread is None:
self.thread = BackgroundTask(self.frequency, self.callback)
self.thread.bus = self.bus
self.thread = BackgroundTask(self.frequency, self.callback,
bus = self.bus)
self.thread.setName(threadname)
self.thread.start()
self.bus.log("Started monitor thread %r." % threadname)

View File

@@ -385,34 +385,43 @@ def check_port(host, port, timeout=1.0):
if s:
s.close()
def wait_for_free_port(host, port):
# Feel free to increase these defaults on slow systems:
free_port_timeout = 0.1
occupied_port_timeout = 1.0
def wait_for_free_port(host, port, timeout=None):
"""Wait for the specified port to become free (drop requests)."""
if not host:
raise ValueError("Host values of '' or None are not allowed.")
if timeout is None:
timeout = free_port_timeout
for trial in range(50):
try:
# we are expecting a free port, so reduce the timeout
check_port(host, port, timeout=0.1)
check_port(host, port, timeout=timeout)
except IOError:
# Give the old server thread time to free the port.
time.sleep(0.1)
time.sleep(timeout)
else:
return
raise IOError("Port %r not free on %r" % (port, host))
def wait_for_occupied_port(host, port):
def wait_for_occupied_port(host, port, timeout=None):
"""Wait for the specified port to become active (receive requests)."""
if not host:
raise ValueError("Host values of '' or None are not allowed.")
if timeout is None:
timeout = occupied_port_timeout
for trial in range(50):
try:
check_port(host, port)
check_port(host, port, timeout=timeout)
except IOError:
return
else:
time.sleep(.1)
time.sleep(timeout)
raise IOError("Port %r not bound on %r" % (port, host))

View File

@@ -90,11 +90,11 @@ class ChannelFailures(Exception):
def handle_exception(self):
"""Append the current exception to self."""
self._exceptions.append(sys.exc_info())
self._exceptions.append(sys.exc_info()[1])
def get_instances(self):
"""Return a list of seen exception instances."""
return [instance for cls, instance, traceback in self._exceptions]
return self._exceptions[:]
def __str__(self):
exception_strings = map(repr, self.get_instances())
@@ -102,8 +102,9 @@ class ChannelFailures(Exception):
__repr__ = __str__
def __nonzero__(self):
def __bool__(self):
return bool(self._exceptions)
__nonzero__ = __bool__
# Use a flag to indicate the state of the bus.
class _StateEnum(object):
@@ -124,6 +125,17 @@ states.STOPPING = states.State()
states.EXITING = states.State()
try:
import fcntl
except ImportError:
max_files = 0
else:
try:
max_files = os.sysconf('SC_OPEN_MAX')
except AttributeError:
max_files = 1024
class Bus(object):
"""Process state-machine and messenger for HTTP site deployment.
@@ -137,6 +149,7 @@ class Bus(object):
states = states
state = states.STOPPED
execv = False
max_cloexec_files = max_files
def __init__(self):
self.execv = False
@@ -173,13 +186,19 @@ class Bus(object):
items = [(self._priorities[(channel, listener)], listener)
for listener in self.listeners[channel]]
items.sort()
try:
items.sort(key=lambda item: item[0])
except TypeError:
# Python 2.3 had no 'key' arg, but that doesn't matter
# since it could sort dissimilar types just fine.
items.sort()
for priority, listener in items:
try:
output.append(listener(*args, **kwargs))
except KeyboardInterrupt:
raise
except SystemExit, e:
except SystemExit:
e = sys.exc_info()[1]
# If we have previous errors ensure the exit code is non-zero
if exc and e.code == 0:
e.code = 1
@@ -221,13 +240,14 @@ class Bus(object):
except:
self.log("Shutting down due to error in start listener:",
level=40, traceback=True)
e_info = sys.exc_info()
e_info = sys.exc_info()[1]
try:
self.exit()
except:
# Any stop/exit errors will be logged inside publish().
pass
raise e_info[0], e_info[1], e_info[2]
# Re-raise the original error
raise e_info
def exit(self):
"""Stop all services and prepare to exit the process."""
@@ -354,8 +374,28 @@ class Bus(object):
args = ['"%s"' % arg for arg in args]
os.chdir(_startup_cwd)
if self.max_cloexec_files:
self._set_cloexec()
os.execv(sys.executable, args)
def _set_cloexec(self):
"""Set the CLOEXEC flag on all open files (except stdin/out/err).
If self.max_cloexec_files is an integer (the default), then on
platforms which support it, it represents the max open files setting
for the operating system. This function will be called just before
the process is restarted via os.execv() to prevent open files
from persisting into the new process.
Set self.max_cloexec_files to 0 to disable this behavior.
"""
for fd in range(3, self.max_cloexec_files): # skip stdin/out/err
try:
flags = fcntl.fcntl(fd, fcntl.F_GETFD)
except IOError:
continue
fcntl.fcntl(fd, fcntl.F_SETFD, flags | fcntl.FD_CLOEXEC)
def stop(self):
"""Stop all services."""
self.state = states.STOPPING
@@ -386,8 +426,7 @@ class Bus(object):
def log(self, msg="", level=20, traceback=False):
"""Log the given message. Append the last traceback if requested."""
if traceback:
exc = sys.exc_info()
msg += "\n" + "".join(_traceback.format_exception(*exc))
msg += "\n" + "".join(_traceback.format_exception(*sys.exc_info()))
self.publish('log', msg, level)
bus = Bus()