Repository navigation
DSH Desktop 0.2.1-rc.1(macOS)主进程崩溃:Uncaught Exception: Error: setTypeOfService EINVAL #11309
Zwyverynb-del
started this conversation in
General
Replies: 1 comment
|
补一份本机的实测,只补主帖和 #9557 里没有的两点;分析结论(方案 A–D)我完全同意,不重复。 1. 触发面可以确定性复现了环境:DSH Desktop
结论:不是取值问题,而是「双向 FIN 之后、handle 尚未释放」这个窗口——优雅关闭的竞态点。调用一旦落在该窗口内必炸;#9557 里「无法稳定复现」这一步可以补上了。 最小复现(零依赖,跑在 Electron 自带 node 上): const net = require('node:net')
const srv = net.createServer(s => { s.on('error', () => {}); s.end('bye') }) // accept 即 FIN
srv.listen(0, '127.0.0.1', async () => {
const s = net.connect({ host: '127.0.0.1', port: srv.address().port, family: 4 })
s.on('error', () => {})
await new Promise(r => s.once('connect', r))
await new Promise(r => setTimeout(r, 20))
s.end() // 客户端也 FIN
await new Promise(r => setTimeout(r, 30))
try { s.setTypeOfService(0) } // writeH1 里那次调用的同形调用
catch (e) { console.log(e.message) } // setTypeOfService EINVAL
s.destroy(); srv.close()
})2. 上游状态:方案 C(等内置副本修好)短期不成立
3. 顺带一个暴露面实测同一份 Electron 内,一个完全不加载 DSH 的脚本连发 3 次全局 |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
摘要
macOS 上 DSH Desktop 偶发弹出 Electron 原生错误框,随后应用退出:
崩溃点在 Electron 主进程:主进程用 Node 全局
fetch(Node 内置 undici 7.29.1)代理渲染层发往dsh-app://app/*的请求;该内置 undici 在writeH1中对socket.setTypeOfService()没有 try/catch。macOS 在部分 socket 状态下让setsockopt(IP_TOS)返回EINVAL,异常未被捕获,按 Electron 默认行为终止主进程。QoS/IP_TOS 标记本身是可选优化,失败不影响请求收发;问题是这个可选失败被当成了致命异常。
环境
process.versions.undici = 7.29.1)client-h1已带 guard)现象 / 崩溃栈
根因
Node 24.21 内置 undici 7.29.1 在
writeH1中无条件执行:request.typeOfService默认0,因此每个 HTTP/1.1 请求都会调用;该调用没有 try/catch。macOS 上
Socket.setTypeOfService在node:net:913抛出ErrnoException(EINVAL),异常沿调用栈逃逸。DSH 主进程
lib/main.js的forwardWebRequest(lib/main.js:8291)使用全局fetch代理页面请求,主进程没有uncaughtException处理器;异常落到 Electron 默认处理,弹出原生错误框并退出应用。对照:DSH 依赖的 npm undici 8.11.2 在
lib/dispatcher/client-h1.js中已把这一步做成 best-effort:也就是说:npm undici 已经处理了这个问题,问题只出在 Node 内置的那份副本。
触发条件
EINVAL与 socket 状态相关。公开报告中常见的状态包括:TLS over HTTP CONNECT、连接复用、半关闭/重连、VPN/代理环境。本地无法稳定复现,属于低频偶发。补充判据:崩溃发生时
~/Library/Logs/DeepSeek Harness/crash-*.log没有对应 host 崩溃记录,符合“主进程崩溃、Electron 原生对话框不落盘”的特征。建议修复(按推荐顺序)
方案 A:主进程启动时包一层
setTypeOfService(最小改动,覆盖所有调用点)在第一次
fetch之前执行(例如lib/main.js模块顶部):要点:
forwardWebRequest、authenticateWebHost以及后续可能新增的 fetch 全部生效。方案 B:让主进程改用自带 undici 8.11.2 的 fetch
forwardWebRequest改用import { fetch } from 'undici'(8.11.2 已带 guard)。注意主进程当前 dependencies 里没有 undici,需要显式加入依赖并确认 asar 内解析路径;这比方案 A 改动大。方案 C:升级 Node 内置 undici
如果后续 Node 版本的内置副本已合入同样的 guard,升级 Electron/Node 即可。需要确认 Node 上游对应的修复版本。
方案 D(仅兜底,不建议单独使用)
主进程注册
process.on('uncaughtException'),仅针对setTypeOfService+EINVAL的形状做过滤,其余错误 rethrow。能挡住弹窗,但会掩盖同类真实错误,建议只作为方案 A 之外的额外防线。验证建议
net.Socket.prototype.setTypeOfService替换为抛EINVAL的桩,驱动一次fetch;ERR_INVALID_ARG_TYPE)仍会抛出,防止 guard 过宽。为什么不是插件问题
DSH 插件运行在 host(cordis profile)与渲染层,不会加载进 Electron 主进程;主进程只执行 asar 内的
lib/main.js,没有插件扩展点。因此无法通过 profile 插件规避此崩溃,供排查参考。参考
node:internal/deps/undici/undici的writeH1All reactions