1
0

move event loop construction to daemon

This commit is contained in:
SomberNight
2018-11-01 16:30:03 +01:00
parent ca8eae919f
commit c2ecfaf239
2 changed files with 41 additions and 34 deletions

View File

@@ -168,6 +168,10 @@ class Network(PrintError):
def __init__(self, config: SimpleConfig=None):
global INSTANCE
INSTANCE = self
self.asyncio_loop = asyncio.get_event_loop()
self._loop_thread = None # type: threading.Thread # set by caller; only used for sanity checks
if config is None:
config = {} # Do not use mutables as default values!
self.config = SimpleConfig(config) if isinstance(config, dict) else config # type: SimpleConfig
@@ -221,17 +225,8 @@ class Network(PrintError):
self.server_queue = None
self.proxy = None
self.asyncio_loop = asyncio.get_event_loop()
self.asyncio_loop.set_exception_handler(self.on_event_loop_exception)
#self.asyncio_loop.set_debug(1)
self._run_forever = asyncio.Future()
self._thread = threading.Thread(target=self.asyncio_loop.run_until_complete,
args=(self._run_forever,),
name='Network')
self._thread.start()
def run_from_another_thread(self, coro):
assert self._thread != threading.current_thread(), 'must not be called from network thread'
assert self._loop_thread != threading.current_thread(), 'must not be called from network thread'
fut = asyncio.run_coroutine_threadsafe(coro, self.asyncio_loop)
return fut.result()
@@ -239,15 +234,6 @@ class Network(PrintError):
def get_instance():
return INSTANCE
def on_event_loop_exception(self, loop, context):
"""Suppress spurious messages it appears we cannot control."""
SUPPRESS_MESSAGE_REGEX = re.compile('SSL handshake|Fatal read error on|'
'SSL error in data received')
message = context.get('message')
if message and SUPPRESS_MESSAGE_REGEX.match(message):
return
loop.default_exception_handler(context)
def with_recent_servers_lock(func):
def func_wrapper(self, *args, **kwargs):
with self.recent_servers_lock:
@@ -845,25 +831,20 @@ class Network(PrintError):
await asyncio.wait_for(self.main_taskgroup.cancel_remaining(), timeout=2)
except (asyncio.TimeoutError, asyncio.CancelledError) as e:
self.print_error(f"exc during main_taskgroup cancellation: {repr(e)}")
try:
self.main_taskgroup = None
self.interface = None # type: Interface
self.interfaces = {} # type: Dict[str, Interface]
self.connecting.clear()
self.server_queue = None
if not full_shutdown:
self.trigger_callback('network_updated')
finally:
if full_shutdown:
self._run_forever.set_result(1)
self.main_taskgroup = None
self.interface = None # type: Interface
self.interfaces = {} # type: Dict[str, Interface]
self.connecting.clear()
self.server_queue = None
if not full_shutdown:
self.trigger_callback('network_updated')
def stop(self):
assert self._thread != threading.current_thread(), 'must not be called from network thread'
assert self._loop_thread != threading.current_thread(), 'must not be called from network thread'
fut = asyncio.run_coroutine_threadsafe(self._stop(full_shutdown=True), self.asyncio_loop)
try:
fut.result(timeout=2)
except (asyncio.TimeoutError, asyncio.CancelledError): pass
self._thread.join(timeout=1)
async def _ensure_there_is_a_main_interface(self):
if self.is_connected():