From 5ba02c531e4d7e68dc8b811ba2ebc7438afe6f16 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Wed, 7 Feb 2018 05:30:18 +0000 Subject: [PATCH] Catch concurrent.futures.CancelledError in websocket code. (#12150) * Catch concurrent.futures.CancelledError in websocket code. * Added a comment about the use of futures.CancelledError --- homeassistant/components/websocket_api.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/websocket_api.py b/homeassistant/components/websocket_api.py index a4bfc46bf832eb..030d1bee579a06 100644 --- a/homeassistant/components/websocket_api.py +++ b/homeassistant/components/websocket_api.py @@ -5,6 +5,7 @@ https://home-assistant.io/developers/websocket_api/ """ import asyncio +from concurrent import futures from contextlib import suppress from functools import partial import json @@ -120,6 +121,11 @@ TYPE_PING) }, extra=vol.ALLOW_EXTRA) +# Define the possible errors that occur when connections are cancelled. +# Originally, this was just asyncio.CancelledError, but issue #9546 showed +# that futures.CancelledErrors can also occur in some situations. +CANCELLATION_ERRORS = (asyncio.CancelledError, futures.CancelledError) + def auth_ok_message(): """Return an auth_ok message.""" @@ -231,7 +237,7 @@ def log_error(self, message1, message2=''): def _writer(self): """Write outgoing messages.""" # Exceptions if Socket disconnected or cancelled by connection handler - with suppress(RuntimeError, asyncio.CancelledError): + with suppress(RuntimeError, *CANCELLATION_ERRORS): while not self.wsock.closed: message = yield from self.to_write.get() if message is None: @@ -363,7 +369,7 @@ def handle_hass_stop(event): self.log_error(msg) self._writer_task.cancel() - except asyncio.CancelledError: + except CANCELLATION_ERRORS: self.debug("Connection cancelled by server") except asyncio.QueueFull: