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.
This commit is contained in:
link2xt
2023-10-04 03:05:33 +00:00
parent a5f0c1613e
commit d51adf2aa0

View File

@@ -1,5 +1,6 @@
import asyncio import asyncio
import json import json
import logging
import os import os
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
@@ -57,16 +58,20 @@ class Rpc:
await self.close() await self.close()
async def reader_loop(self) -> None: async def reader_loop(self) -> None:
while True: try:
line = await self.process.stdout.readline() # noqa while True:
if not line: # EOF line = await self.process.stdout.readline() # noqa
break if not line: # EOF
response = json.loads(line) break
if "id" in response: response = json.loads(line)
fut = self.request_events.pop(response["id"]) if "id" in response:
fut.set_result(response) fut = self.request_events.pop(response["id"])
else: fut.set_result(response)
print(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: async def get_queue(self, account_id: int) -> asyncio.Queue:
if account_id not in self.event_queues: if account_id not in self.event_queues:
@@ -75,13 +80,17 @@ class Rpc:
async def events_loop(self) -> None: async def events_loop(self) -> None:
"""Requests new events and distributes them between queues.""" """Requests new events and distributes them between queues."""
while True: try:
if self.closing: while True:
return if self.closing:
event = await self.get_next_event() return
account_id = event["contextId"] event = await self.get_next_event()
queue = await self.get_queue(account_id) account_id = event["contextId"]
await queue.put(event["event"]) 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]: async def wait_for_event(self, account_id: int) -> Optional[dict]:
"""Waits for the next event from the given account and returns it.""" """Waits for the next event from the given account and returns it."""