From 31fe1d28e8ab48acc035bb65ef3566937098ee08 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 18 Dec 2016 00:14:59 -0800 Subject: [PATCH] Gracefully exit with async logger (#4965) * Gracefully exit with async logger * Lint --- homeassistant/core.py | 5 ++--- homeassistant/util/logging.py | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/homeassistant/core.py b/homeassistant/core.py index 7daab159f21..de272beeeea 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -298,9 +298,8 @@ class HomeAssistant(object): # cleanup async layer from python logging if self.data.get(DATA_ASYNCHANDLER): handler = self.data.pop(DATA_ASYNCHANDLER) - logger = logging.getLogger('') - handler.close() - logger.removeHandler(handler) + logging.getLogger('').removeHandler(handler) + yield from handler.async_close(blocking=True) self.loop.stop() diff --git a/homeassistant/util/logging.py b/homeassistant/util/logging.py index 1ddec0bc6a1..0a1218f5796 100644 --- a/homeassistant/util/logging.py +++ b/homeassistant/util/logging.py @@ -49,6 +49,23 @@ class AsyncHandler(object): """Wrap close to handler.""" self.emit(None) + @asyncio.coroutine + def async_close(self, blocking=False): + """Close the handler. + + When blocking=True, will wait till closed. + """ + self.close() + + if blocking: + # Python 3.4.4+ + # pylint: disable=no-member + if hasattr(self._queue, 'join'): + yield from self._queue.join() + else: + while not self._queue.empty(): + yield from asyncio.sleep(0, loop=self.loop) + def emit(self, record): """Process a record.""" ident = self.loop.__dict__.get("_thread_ident") @@ -66,15 +83,23 @@ class AsyncHandler(object): def _process(self): """Process log in a thread.""" + support_join = hasattr(self._queue, 'task_done') + while True: record = run_coroutine_threadsafe( self._queue.get(), self.loop).result() + # pylint: disable=no-member + if record is None: self.handler.close() + if support_join: + self.loop.call_soon_threadsafe(self._queue.task_done) return self.handler.emit(record) + if support_join: + self.loop.call_soon_threadsafe(self._queue.task_done) def createLock(self): """Ignore lock stuff."""