From 5d3f54b02a04378362dbebe2fc6608db5bef1dd3 Mon Sep 17 00:00:00 2001
From: acgnhik <acgnhik@outlook.com>
Date: Thu, 12 Oct 2023 19:20:35 +0800
Subject: [PATCH] fix: fix `Unclosed client session`

fix #176
---
 src/blrec/application.py       | 14 ++++++++++++--
 src/blrec/task/task.py         | 22 +++++++++++++++-------
 src/blrec/task/task_manager.py |  3 ++-
 3 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/src/blrec/application.py b/src/blrec/application.py
index a27e6d2..3ff0e10 100644
--- a/src/blrec/application.py
+++ b/src/blrec/application.py
@@ -1,6 +1,7 @@
 import asyncio
 import logging
 import os
+from contextlib import suppress
 from typing import Iterator, List, Optional
 
 import attr
@@ -102,8 +103,13 @@ class Application:
         self._setup()
         logger.debug(f'Default umask {os.umask(0o000)}')
         logger.info(f'Launched Application v{__version__}')
-        task = asyncio.create_task(self._task_manager.load_all_tasks())
-        task.add_done_callback(exception_callback)
+        self._loading_task = asyncio.create_task(self._task_manager.load_all_tasks())
+
+        def callback(future: asyncio.Future) -> None:  # type: ignore
+            del self._loading_task
+
+        self._loading_task.add_done_callback(exception_callback)
+        self._loading_task.add_done_callback(callback)
 
     async def exit(self) -> None:
         logger.info('Exiting Application...')
@@ -116,6 +122,10 @@ class Application:
         logger.info('Aborted Application')
 
     async def _exit(self, force: bool = False) -> None:
+        if hasattr(self, '_loading_task'):
+            self._loading_task.cancel()
+            with suppress(asyncio.CancelledError):
+                await self._loading_task
         await self._task_manager.stop_all_tasks(force=force)
         await self._task_manager.destroy_all_tasks()
         self._destroy()
diff --git a/src/blrec/task/task.py b/src/blrec/task/task.py
index 8b1574a..d22826b 100644
--- a/src/blrec/task/task.py
+++ b/src/blrec/task/task.py
@@ -1,5 +1,6 @@
 import logging
 import os
+from contextlib import suppress
 from pathlib import PurePath
 from typing import Iterator, List, Optional
 
@@ -565,22 +566,29 @@ class RecordTask:
         self._destroy_danmaku_client()
 
     def _destroy_danmaku_client(self) -> None:
-        del self._danmaku_client
+        with suppress(AttributeError):
+            del self._danmaku_client
 
     def _destroy_live_monitor(self) -> None:
-        del self._live_monitor
+        with suppress(AttributeError):
+            del self._live_monitor
 
     def _destroy_live_event_submitter(self) -> None:
-        del self._live_event_submitter
+        with suppress(AttributeError):
+            del self._live_event_submitter
 
     def _destroy_recorder(self) -> None:
-        del self._recorder
+        with suppress(AttributeError):
+            del self._recorder
 
     def _destroy_recorder_event_submitter(self) -> None:
-        del self._recorder_event_submitter
+        with suppress(AttributeError):
+            del self._recorder_event_submitter
 
     def _destroy_postprocessor(self) -> None:
-        del self._postprocessor
+        with suppress(AttributeError):
+            del self._postprocessor
 
     def _destroy_postprocessor_event_submitter(self) -> None:
-        del self._postprocessor_event_submitter
+        with suppress(AttributeError):
+            del self._postprocessor_event_submitter
diff --git a/src/blrec/task/task_manager.py b/src/blrec/task/task_manager.py
index 55d6f86..5daa221 100644
--- a/src/blrec/task/task_manager.py
+++ b/src/blrec/task/task_manager.py
@@ -106,8 +106,9 @@ class RecordTaskManager:
                 await task.enable_monitor()
             if settings.enable_recorder:
                 await task.enable_recorder()
-        except Exception as e:
+        except BaseException as e:
             logger.error(f'Failed to add task {settings.room_id} due to: {repr(e)}')
+            await task.destroy()
             del self._tasks[settings.room_id]
             raise