fix: prevent crashes from process.exit, empty array destructuring and native module calls

This commit is contained in:
xmk23333 2026-01-15 23:44:28 +08:00
parent a28f576d78
commit 9e0f27aea3
6 changed files with 47 additions and 23 deletions

View File

@ -1,3 +1,11 @@
# 1.9.1
## 修复 (Fix)
- 修复 Windows 下以管理员重启开启 TUN 时因单实例锁冲突导致的闪退问题
- 修复托盘菜单开启 TUN 时管理员重启后继续执行导致的竞态问题
- 修复关键资源文件复制失败时静默跳过导致内核启动异常的问题
# 1.9.0
## 新功能 (Feat)

View File

@ -282,7 +282,11 @@ export async function restartAsAdmin(forTun: boolean = true): Promise<void> {
managerLogger.info('Restarting as administrator with command', command)
// 先启动 PowerShell它会等待 1 秒),然后立即退出当前进程
exec(command, { windowsHide: true })
exec(command, { windowsHide: true }, (error) => {
if (error) {
managerLogger.error('Failed to start PowerShell for admin restart', error)
}
})
managerLogger.info('PowerShell command started, quitting app immediately')
app.exit(0)
}

View File

@ -87,13 +87,13 @@ async function checkHighPrivilegeCoreEarly(): Promise<void> {
if (choice === 0) {
try {
await restartAsAdmin(false)
process.exit(0)
app.exit(0)
} catch (error) {
safeShowErrorBox('common.error.adminRequired', `${error}`)
process.exit(1)
app.exit(1)
}
} else {
process.exit(0)
app.exit(0)
}
} catch (e) {
mainLogger.error('Failed to check high privilege core', e)
@ -151,12 +151,14 @@ app.whenReady().then(async () => {
try {
initCoreWatcher()
const [startPromise] = await startCore()
startPromise.then(async () => {
await initProfileUpdater()
await initWebdavBackupScheduler()
await checkAdminRestartForTun()
})
const startPromises = await startCore()
if (startPromises.length > 0) {
startPromises[0].then(async () => {
await initProfileUpdater()
await initWebdavBackupScheduler()
await checkAdminRestartForTun()
})
}
} catch (e) {
safeShowErrorBox('mihomo.error.coreStartFailed', `${e}`)
}

View File

@ -253,6 +253,9 @@ export const buildContextMenu = async (): Promise<Menu> => {
}
} catch (error) {
await trayLogger.warn('Permission check failed in tray', error)
item.checked = false
ipcMain.emit('updateTrayMenu')
return
}
await patchControledMihomoConfig({ tun: { enable }, dns: { enable: true } })

View File

@ -97,10 +97,15 @@ async function enableSysProxy(): Promise<void> {
}
} else {
// Windows / Linux 直接使用 sysproxy-rs
if (mode === 'auto') {
triggerAutoProxy(true, `http://${proxyHost}:${pacPort}/pac`)
} else {
triggerManualProxy(true, proxyHost, port, bypass.join(','))
try {
if (mode === 'auto') {
triggerAutoProxy(true, `http://${proxyHost}:${pacPort}/pac`)
} else {
triggerManualProxy(true, proxyHost, port, bypass.join(','))
}
} catch (error) {
await proxyLogger.error('Failed to enable system proxy', error)
throw error
}
}
}
@ -114,8 +119,13 @@ async function disableSysProxy(): Promise<void> {
)
} else {
// Windows / Linux 直接使用 sysproxy-rs
triggerAutoProxy(false, '')
triggerManualProxy(false, '', 0, '')
try {
triggerAutoProxy(false, '')
triggerManualProxy(false, '', 0, '')
} catch (error) {
await proxyLogger.error('Failed to disable system proxy', error)
throw error
}
}
}

View File

@ -189,14 +189,11 @@ async function initFiles(): Promise<void> {
await cp(sourcePath, targetPath, { recursive: true, force: true })
} catch (error: unknown) {
const code = (error as NodeJS.ErrnoException).code
if (code === 'EPERM' || code === 'EBUSY') {
// 文件被占用,如果目标已存在则跳过
if (existsSync(targetPath)) {
await initLogger.warn(`Skipping ${file}: file is in use`)
return
}
// 文件被占用或权限问题,如果目标已存在则跳过
if ((code === 'EPERM' || code === 'EBUSY' || code === 'EACCES') && existsSync(targetPath)) {
await initLogger.warn(`Skipping ${file}: file is in use or permission denied`)
return
}
// 其他错误或目标不存在时,向上抛出让 criticalFiles 检查处理
throw error
}
})