cnbugs
|
74a68fcbd0
|
fix(socks5): 加 Socks5Server.is_alive() 健康探活, sync_instances 自动重启死实例
背景:
Socks5Server.running 是乐观标记, start() 之后到 stop() 之前一直 True。
但子线程 event loop 崩了/端口被外部抢占/worker 被 gunicorn 杀 等情况,
self.running 仍为 True, DB 里 inst.running=true 是谎言。
上次 40080 实例莫名停止就是这种状态。
变更:
+ Socks5Server.is_alive() thread.is_alive() + server.is_serving()
M InstanceManager.sync_instances 启动前先探活, 死的从 _instances 摘掉
让'启动缺失'循环用 DB 配置重建它
M inst.running = srv.is_alive() 不再用乐观的 srv.running
测试:
+ tests/e2e_socks5_lifecycle.py 完整 SOCKS5 userpass 生命周期, 拦住
_record_stats 里 await 同步方法的回归
+ tests/e2e_health_check.py 模拟 Socks5Server 死了, sync_instances
自动重启; 反向验证: 注释掉健康检查就 fail
验证:
- 正向 (修复在): lifecycle PASS, health PASS, smoke tunnel PASS
- 反向 (回滚修复): 两个 e2e 都正确 FAIL, 证明测试真的能抓回归
|
2026-08-10 23:45:29 +08:00 |
|
cnbugs
|
22b9427ca5
|
fix(socks5): 去掉 _record_stats 里对同步方法 add_traffic 的 await
回归: ee8c0b8 引入的 _forward timeout 修复没改 _record_stats,
但烟雾测试里 FakeUserService.add_traffic 误写成 async def 掩盖了
这个 bug。生产机 15:32:08 命中:
socks.engine: 记录统计失败: object NoneType can't be used in 'await'
gunicorn: [CRITICAL] WORKER TIMEOUT (pid:428355)
gunicorn: Error handling request (no URI read)
add_traffic 是 UserService 里的 def (非 async), 不能 await。错误地
await 一个 None 返回值会让 worker 在协程上下文里抛 TypeError,
被 _record_stats 的 except 吃掉, 但 worker 进入不可服务状态,
触发 30s gunicorn timeout, 表现就是 40080 实例莫名停止。
注意 log_event 是 async, 仍需 await; add_traffic 是 def, 不 await。
修法:
engine/server.py:472 去掉 await, 同步调用 add_traffic
tests/smoke_tunnel_timeout.py FakeUserService.add_traffic 改为
def, 模拟真实 UserService 签名,
防止烟雾测试再次漏掉此类 bug
线上已临时恢复 40080 (curl POST /api/instances/2/restart),
|
2026-08-10 23:35:30 +08:00 |
|
cnbugs
|
ee8c0b83db
|
fix(socks5): 隧道转发阶段补 idle timeout,防慢客户端耗尽 fd
之前 _forward() 直接 await src.read(TUNNEL_CHUNK),无 timeout。
已通过 SOCKS5 握手的客户端可以一直挂着不发数据,占住 fd 不放,
直到 LimitNOFILE=65535 才被内核拒。
握手/认证/请求阶段已经全部用 asyncio.wait_for + config.timeout,
但同一个 timeout 字段没覆盖 tunnel 阶段,语义不一致。
修复:
engine/server.py:381-407 _forward 每次 read 包 wait_for, 触发
TimeoutError 时 break 走 _tunnel 的 finally
清理 (关闭 writer, 取消对端 forward 任务)
验证 (tests/smoke_tunnel_timeout.py):
- 客户端只握手不进 tunnel, 服务端在 config.timeout 秒后关闭
- 反向: git stash 掉修复, 客户端永远不被关闭, 服务端报
'Task was destroyed but it is pending' — 证明修复前后行为差
异真实存在
models.Instance.timeout 注释: 说明该字段覆盖 tunnel 阶段
|
2026-08-10 23:28:46 +08:00 |
|