From d51adf2aa0730faea84b04d215e15f51cbadd874 Mon Sep 17 00:00:00 2001 From: link2xt Date: Wed, 4 Oct 2023 03:05:33 +0000 Subject: [PATCH] feat(deltachat-rpc-client): log exceptions when long-running tasks die For example, reader_loop() may die if readline() tries to read too large line and thows an exception. We want to at least log the exception in this case. --- .../src/deltachat_rpc_client/rpc.py | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/deltachat-rpc-client/src/deltachat_rpc_client/rpc.py b/deltachat-rpc-client/src/deltachat_rpc_client/rpc.py index df65ffea1..c43c363c1 100644 --- a/deltachat-rpc-client/src/deltachat_rpc_client/rpc.py +++ b/deltachat-rpc-client/src/deltachat_rpc_client/rpc.py @@ -1,5 +1,6 @@ import asyncio import json +import logging import os from typing import Any, Dict, Optional @@ -57,16 +58,20 @@ class Rpc: await self.close() async def reader_loop(self) -> None: - while True: - line = await self.process.stdout.readline() # noqa - if not line: # EOF - break - response = json.loads(line) - if "id" in response: - fut = self.request_events.pop(response["id"]) - fut.set_result(response) - else: - print(response) + try: + while True: + line = await self.process.stdout.readline() # noqa + if not line: # EOF + break + response = json.loads(line) + if "id" in response: + fut = self.request_events.pop(response["id"]) + fut.set_result(response) + else: + print(response) + except Exception: + # Log an exception if the reader loop dies. + logging.exception("Exception in the reader loop") async def get_queue(self, account_id: int) -> asyncio.Queue: if account_id not in self.event_queues: @@ -75,13 +80,17 @@ class Rpc: async def events_loop(self) -> None: """Requests new events and distributes them between queues.""" - while True: - if self.closing: - return - event = await self.get_next_event() - account_id = event["contextId"] - queue = await self.get_queue(account_id) - await queue.put(event["event"]) + try: + while True: + if self.closing: + return + event = await self.get_next_event() + account_id = event["contextId"] + queue = await self.get_queue(account_id) + await queue.put(event["event"]) + except Exception: + # Log an exception if the event loop dies. + logging.exception("Exception in the event loop") async def wait_for_event(self, account_id: int) -> Optional[dict]: """Waits for the next event from the given account and returns it."""