diff options
Diffstat (limited to 'rpki/async.py')
-rw-r--r-- | rpki/async.py | 79 |
1 files changed, 14 insertions, 65 deletions
diff --git a/rpki/async.py b/rpki/async.py index 75b4b656..74143bd1 100644 --- a/rpki/async.py +++ b/rpki/async.py @@ -131,6 +131,7 @@ class timer(object): """ Debug logging. """ + if self.gc_debug: bt = traceback.extract_stack(limit = 3) logger.debug("%s from %s:%d", msg, bt[0][0], bt[0][1]) @@ -140,6 +141,7 @@ class timer(object): Set a timer. Argument can be a datetime, to specify an absolute time, or a timedelta, to specify an offset time. """ + if self.gc_debug: self.trace("Setting %r to %r" % (self, when)) if isinstance(when, rpki.sundial.timedelta): @@ -162,6 +164,7 @@ class timer(object): """ Cancel a timer, if it was set. """ + if self.gc_debug: self.trace("Canceling %r" % self) try: @@ -174,6 +177,7 @@ class timer(object): """ Test whether this timer is currently set. """ + return self in timer_queue def set_handler(self, handler): @@ -184,12 +188,14 @@ class timer(object): bound method to an object in a class representing a network connection). """ + self.handler = handler def set_errback(self, errback): """ Set a timer's errback. Like set_handler(), for errbacks. """ + self.errback = errback @classmethod @@ -202,6 +208,7 @@ class timer(object): called, so that even if new events keep getting scheduled, we'll return to the I/O loop reasonably quickly. """ + now = rpki.sundial.now() while timer_queue and now >= timer_queue[0].when: t = timer_queue.pop(0) @@ -233,6 +240,7 @@ class timer(object): the same units (argh!), and we're not doing anything that hair-triggered, so rounding up is simplest. """ + if not timer_queue: return None now = rpki.sundial.now() @@ -251,6 +259,7 @@ class timer(object): queue content, but this way we can notify subclasses that provide their own cancel() method. """ + while timer_queue: timer_queue.pop(0).cancel() @@ -258,12 +267,14 @@ def _raiseExitNow(signum, frame): """ Signal handler for event_loop(). """ + raise ExitNow def exit_event_loop(): """ Force exit from event_loop(). """ + raise ExitNow def event_defer(handler, delay = rpki.sundial.timedelta(seconds = 0)): @@ -271,6 +282,7 @@ def event_defer(handler, delay = rpki.sundial.timedelta(seconds = 0)): Use a near-term (default: zero interval) timer to schedule an event to run after letting the I/O system have a turn. """ + timer(handler).set(delay) ## @var debug_event_timing @@ -282,6 +294,7 @@ def event_loop(catch_signals = (signal.SIGINT, signal.SIGTERM)): """ Replacement for asyncore.loop(), adding timer and signal support. """ + old_signal_handlers = {} while True: save_sigs = len(old_signal_handlers) == 0 @@ -323,71 +336,6 @@ def event_loop(catch_signals = (signal.SIGINT, signal.SIGTERM)): for sig in old_signal_handlers: signal.signal(sig, old_signal_handlers[sig]) -class sync_wrapper(object): - """ - Synchronous wrapper around asynchronous functions. Running in - asynchronous mode at all times makes sense for event-driven daemons, - but is kind of tedious for simple scripts, hence this wrapper. - - The wrapped function should take at least two arguments: a callback - function and an errback function. If any arguments are passed to - the wrapper, they will be passed as additional arguments to the - wrapped function. - """ - - res = None - err = None - fin = False - - def __init__(self, func, disable_signal_handlers = False): - self.func = func - self.disable_signal_handlers = disable_signal_handlers - - def cb(self, res = None): - """ - Wrapped code has requested normal termination. Store result, and - exit the event loop. - """ - self.res = res - self.fin = True - logger.debug("%r callback with result %r", self, self.res) - raise ExitNow - - def eb(self, err): - """ - Wrapped code raised an exception. Store exception data, then exit - the event loop. - """ - exc_info = sys.exc_info() - self.err = exc_info if exc_info[1] is err else err - self.fin = True - logger.debug("%r errback with exception %r", self, self.err) - raise ExitNow - - def __call__(self, *args, **kwargs): - - def thunk(): - try: - self.func(self.cb, self.eb, *args, **kwargs) - except ExitNow: - raise - except Exception, e: - self.eb(e) - - event_defer(thunk) - if self.disable_signal_handlers: - event_loop(catch_signals = ()) - else: - event_loop() - if not self.fin: - logger.warning("%r event_loop terminated without callback or errback", self) - if self.err is None: - return self.res - elif isinstance(self.err, tuple): - raise self.err[0], self.err[1], self.err[2] - else: - raise self.err - class gc_summary(object): """ Periodic summary of GC state, for tracking down memory bloat. @@ -405,6 +353,7 @@ class gc_summary(object): """ Collect and log GC state for this period, reset timer. """ + logger.debug("gc_summary: Running gc.collect()") gc.collect() logger.debug("gc_summary: Summarizing (threshold %d)", self.threshold) |