diff --git a/tangostationcontrol/tangostationcontrol/common/asyncio.py b/tangostationcontrol/tangostationcontrol/common/asyncio.py
index f716bc83a9fc6cb2e01fa57d97c7c111539aa93a..5a61f4171a3a021fbe3d9555fc5a9a17db8a31b8 100644
--- a/tangostationcontrol/tangostationcontrol/common/asyncio.py
+++ b/tangostationcontrol/tangostationcontrol/common/asyncio.py
@@ -2,11 +2,14 @@
 # SPDX-License-Identifier: Apache-2.0
 
 import asyncio
+import logging
 from contextlib import suppress
 from concurrent.futures import Future, CancelledError
 from threading import Thread
 from typing import Callable
 
+logger = logging.getLogger()
+
 
 class EventLoopThread:
     """A forever running thread that keeps executing the given event_loop."""
@@ -88,7 +91,12 @@ class PeriodicTask:
 
     async def _call_periodically(self):
         while not self.done:
-            await self.func()
+            try:
+                await self.func()
+            except (CancelledError, asyncio.CancelledError):
+                raise
+            except Exception as ex:
+                logger.exception(f"Periodic task {self.func} raised an exception")
 
             # TODO(JDM): Calculate how long to sleep to have the runtime of
             #            func be subtracted.