raceDial在首个连接成功后cancel剩余拨号goroutine时,dial goroutine 的select有两个同时就绪的case(缓冲channel可发送 vs raceCtx.Done()), Go随机选择可能导致结果未发送,使drain循环永久阻塞,进而导致daemon 持有d.mu死锁,所有IPC命令(stats/stop/新start)全部阻塞。 DNS解析返回IPv4+IPv6双地址时触发此bug,约50%概率死锁。 修复:移除select,直接发送到缓冲channel(容量=len(ips)永不阻塞), 多余连接由drain循环负责关闭。
- 新增竞速拨号器(racedial.go):域名连接时并行解析所有A/AAAA记录, 同时对所有IP发起TCP连接,第一个成功的胜出,确保选择延迟最低的地址 - ServerProfile新增IPPreference字段(auto/v4/v6),支持用户指定IP版本偏好 - 填写服务器IP时跳过域名解析直接使用IP,顺序failover - 连接成功后状态栏显示「已连接 (域名 -> 实际IP)」 - DB迁移v6:server_profiles表添加ip_preference列 - WebSocket拨号与HTTP登录均使用竞速拨号器 - 补充中英文i18n翻译