fix: 修复 GeneratorExit 和 Task destroyed 警告
问题: 协程被取消/销毁时,finally 块中的异步操作触发 GeneratorExit 原因: GeneratorExit 是 BaseException 子类,不会被 Exception 捕获 修复内容: - server.py handle(): 捕获 CancelledError + GeneratorExit - server.py _tunnel(): 被取消时不执行 _record_stats() 异步操作 - instances.py _accept_connection(): 添加异常处理和 writer 关闭 - 所有取消场景都静默处理(不抛异常/不记录错误日志)
This commit is contained in:
+17
-8
@@ -114,14 +114,23 @@ class Socks5Server:
|
|||||||
)
|
)
|
||||||
|
|
||||||
async def _accept_connection(self, reader, writer):
|
async def _accept_connection(self, reader, writer):
|
||||||
with self._lock:
|
try:
|
||||||
self._active_connections += 1
|
with self._lock:
|
||||||
handler = ConnectionHandler(
|
self._active_connections += 1
|
||||||
reader, writer, self.config, self.user_service,
|
handler = ConnectionHandler(
|
||||||
flask_app=self.flask_app,
|
reader, writer, self.config, self.user_service,
|
||||||
on_close_cb=self._on_connection_close
|
flask_app=self.flask_app,
|
||||||
)
|
on_close_cb=self._on_connection_close
|
||||||
await handler.handle()
|
)
|
||||||
|
await handler.handle()
|
||||||
|
except (asyncio.CancelledError, GeneratorExit):
|
||||||
|
# 服务器关闭时正常取消,不记录错误
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
writer.close()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
def _on_connection_close(self, handler):
|
def _on_connection_close(self, handler):
|
||||||
with self._lock:
|
with self._lock:
|
||||||
|
|||||||
+11
-4
@@ -104,6 +104,9 @@ class ConnectionHandler:
|
|||||||
log.debug("[%s] 超时", self.conn_id)
|
log.debug("[%s] 超时", self.conn_id)
|
||||||
except ConnectionError:
|
except ConnectionError:
|
||||||
log.debug("[%s] 连接错误", self.conn_id)
|
log.debug("[%s] 连接错误", self.conn_id)
|
||||||
|
except (asyncio.CancelledError, GeneratorExit):
|
||||||
|
# 正常关闭,不记录错误
|
||||||
|
pass
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception("[%s] 异常: %s", self.conn_id, e)
|
log.exception("[%s] 异常: %s", self.conn_id, e)
|
||||||
finally:
|
finally:
|
||||||
@@ -329,6 +332,7 @@ class ConnectionHandler:
|
|||||||
async def _tunnel(self, dst_reader, dst_writer):
|
async def _tunnel(self, dst_reader, dst_writer):
|
||||||
"""双向隧道转发。"""
|
"""双向隧道转发。"""
|
||||||
f1 = f2 = None
|
f1 = f2 = None
|
||||||
|
cancelled = False
|
||||||
try:
|
try:
|
||||||
# 获取限速参数
|
# 获取限速参数
|
||||||
user = None
|
user = None
|
||||||
@@ -349,7 +353,9 @@ class ConnectionHandler:
|
|||||||
await asyncio.gather(f1, f2, return_exceptions=True)
|
await asyncio.gather(f1, f2, return_exceptions=True)
|
||||||
|
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
pass
|
cancelled = True
|
||||||
|
except GeneratorExit:
|
||||||
|
cancelled = True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception("[%s] 隧道异常: %s", self.conn_id, e)
|
log.exception("[%s] 隧道异常: %s", self.conn_id, e)
|
||||||
finally:
|
finally:
|
||||||
@@ -359,11 +365,12 @@ class ConnectionHandler:
|
|||||||
task.cancel()
|
task.cancel()
|
||||||
try:
|
try:
|
||||||
await task
|
await task
|
||||||
except asyncio.CancelledError:
|
except (asyncio.CancelledError, GeneratorExit):
|
||||||
pass
|
pass
|
||||||
self._close_streams(dst_reader, dst_writer)
|
self._close_streams(dst_reader, dst_writer)
|
||||||
# 记录最终统计
|
# 记录最终统计 - 协程被取消时不做异步操作(避免 GeneratorExit)
|
||||||
await self._record_stats()
|
if not cancelled:
|
||||||
|
await self._record_stats()
|
||||||
|
|
||||||
async def _forward(self, src, dst, direction, speed_limit_mbps, user):
|
async def _forward(self, src, dst, direction, speed_limit_mbps, user):
|
||||||
"""单向转发,带限速。"""
|
"""单向转发,带限速。"""
|
||||||
|
|||||||
Reference in New Issue
Block a user