Dmitri Bogomolov
7a89109fc9
and use logging without risk of circular import. Only subpackage that imports from debug is bitmessageqt - because it also uses debug.resetLogging(). Instead of from debug import logger is now recommended to use: import logging logger = logging.getLogger('default') All subclasses of StoppableThread now have a logger attribute. All threading related stuff except for set_thread_name() was moved from helper_threading to network.threads. Fixed two my mistakes from previous edit of debug in a1a8d3a: - logger.handlers is not dict but iterable - sys.excepthook should be set unconditionally
50 lines
1.1 KiB
Python
50 lines
1.1 KiB
Python
"""Threading primitives for the network package"""
|
|
|
|
import logging
|
|
import random
|
|
import threading
|
|
from contextlib import contextmanager
|
|
|
|
|
|
class StoppableThread(threading.Thread):
|
|
"""Base class for application threads with stopThread method"""
|
|
name = None
|
|
logger = logging.getLogger('default')
|
|
|
|
def __init__(self, name=None):
|
|
if name:
|
|
self.name = name
|
|
super(StoppableThread, self).__init__(name=self.name)
|
|
self.stop = threading.Event()
|
|
self._stopped = False
|
|
random.seed()
|
|
self.logger.info('Init thread %s', self.name)
|
|
|
|
def stopThread(self):
|
|
"""Stop the thread"""
|
|
self._stopped = True
|
|
self.stop.set()
|
|
|
|
|
|
class BusyError(threading.ThreadError):
|
|
"""
|
|
Thread error raised when another connection holds the lock
|
|
we are trying to acquire.
|
|
"""
|
|
pass
|
|
|
|
|
|
@contextmanager
|
|
def nonBlocking(lock):
|
|
"""
|
|
A context manager which acquires given lock non-blocking
|
|
and raises BusyError if failed to acquire.
|
|
"""
|
|
locked = lock.acquire(False)
|
|
if not locked:
|
|
raise BusyError
|
|
try:
|
|
yield
|
|
finally:
|
|
lock.release()
|