From ae8334140df9bbcd2180b92882c684b7d34f6ce1 Mon Sep 17 00:00:00 2001 From: Your Name Date: Fri, 17 Jul 2026 00:06:01 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20GeneratorExit=20?= =?UTF-8?q?=E5=92=8C=20Task=20destroyed=20=E8=AD=A6=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题: 协程被取消/销毁时,finally 块中的异步操作触发 GeneratorExit 原因: GeneratorExit 是 BaseException 子类,不会被 Exception 捕获 修复内容: - server.py handle(): 捕获 CancelledError + GeneratorExit - server.py _tunnel(): 被取消时不执行 _record_stats() 异步操作 - instances.py _accept_connection(): 添加异常处理和 writer 关闭 - 所有取消场景都静默处理(不抛异常/不记录错误日志) --- engine/instances.py | 25 +++++++++++++++++-------- engine/server.py | 15 +++++++++++---- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/engine/instances.py b/engine/instances.py index 9c40689..8e9901f 100644 --- a/engine/instances.py +++ b/engine/instances.py @@ -114,14 +114,23 @@ class Socks5Server: ) async def _accept_connection(self, reader, writer): - with self._lock: - self._active_connections += 1 - handler = ConnectionHandler( - reader, writer, self.config, self.user_service, - flask_app=self.flask_app, - on_close_cb=self._on_connection_close - ) - await handler.handle() + try: + with self._lock: + self._active_connections += 1 + handler = ConnectionHandler( + reader, writer, self.config, self.user_service, + flask_app=self.flask_app, + on_close_cb=self._on_connection_close + ) + await handler.handle() + except (asyncio.CancelledError, GeneratorExit): + # 服务器关闭时正常取消,不记录错误 + pass + finally: + try: + writer.close() + except Exception: + pass def _on_connection_close(self, handler): with self._lock: diff --git a/engine/server.py b/engine/server.py index dd9cd2a..c7d4f2b 100644 --- a/engine/server.py +++ b/engine/server.py @@ -104,6 +104,9 @@ class ConnectionHandler: log.debug("[%s] 超时", self.conn_id) except ConnectionError: log.debug("[%s] 连接错误", self.conn_id) + except (asyncio.CancelledError, GeneratorExit): + # 正常关闭,不记录错误 + pass except Exception as e: log.exception("[%s] 异常: %s", self.conn_id, e) finally: @@ -329,6 +332,7 @@ class ConnectionHandler: async def _tunnel(self, dst_reader, dst_writer): """双向隧道转发。""" f1 = f2 = None + cancelled = False try: # 获取限速参数 user = None @@ -349,7 +353,9 @@ class ConnectionHandler: await asyncio.gather(f1, f2, return_exceptions=True) except asyncio.CancelledError: - pass + cancelled = True + except GeneratorExit: + cancelled = True except Exception as e: log.exception("[%s] 隧道异常: %s", self.conn_id, e) finally: @@ -359,11 +365,12 @@ class ConnectionHandler: task.cancel() try: await task - except asyncio.CancelledError: + except (asyncio.CancelledError, GeneratorExit): pass self._close_streams(dst_reader, dst_writer) - # 记录最终统计 - await self._record_stats() + # 记录最终统计 - 协程被取消时不做异步操作(避免 GeneratorExit) + if not cancelled: + await self._record_stats() async def _forward(self, src, dst, direction, speed_limit_mbps, user): """单向转发,带限速。"""