Skip to content

Commit 32c0c84

Browse files
author
Pompurin404
committed
Improve core management
1 parent bde9acf commit 32c0c84

File tree

5 files changed

+88
-49
lines changed

5 files changed

+88
-49
lines changed

src/main/config/profile.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { getControledMihomoConfig } from './controledMihomo'
22
import { profileConfigPath, profilePath } from '../utils/dirs'
3-
import { restartCore } from '../core/manager'
3+
import { startCore } from '../core/manager'
44
import { getAppConfig } from './app'
55
import { window } from '..'
66
import axios from 'axios'
@@ -28,7 +28,7 @@ export async function changeCurrentProfile(id: string): Promise<void> {
2828
profileConfig.current = id
2929
getCurrentProfile(true)
3030
try {
31-
restartCore()
31+
await startCore()
3232
} catch (e) {
3333
profileConfig.current = oldId
3434
getCurrentProfile(true)
@@ -38,7 +38,7 @@ export async function changeCurrentProfile(id: string): Promise<void> {
3838
}
3939
}
4040

41-
export async function updateProfileItem(item: IProfileItem): Promise<void> {
41+
export function updateProfileItem(item: IProfileItem): void {
4242
const index = profileConfig.items.findIndex((i) => i.id === item.id)
4343
profileConfig.items[index] = item
4444
fs.writeFileSync(profileConfigPath(), yaml.stringify(profileConfig))
@@ -174,11 +174,11 @@ export function getProfileStr(id: string): string {
174174
return fs.readFileSync(profilePath(id), 'utf-8')
175175
}
176176

177-
export function setProfileStr(id: string, content: string): void {
177+
export async function setProfileStr(id: string, content: string): Promise<void> {
178178
fs.writeFileSync(profilePath(id), content, 'utf-8')
179179
if (id === getProfileConfig().current) {
180180
getCurrentProfile(true)
181-
restartCore()
181+
await startCore()
182182
}
183183
}
184184

src/main/core/manager.ts

+74-38
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ChildProcess, execFileSync, execSync, spawn } from 'child_process'
1+
import { ChildProcess, execFile, execSync, spawn } from 'child_process'
22
import {
33
logPath,
44
mihomoCorePath,
@@ -12,61 +12,97 @@ import { dialog, safeStorage } from 'electron'
1212
import fs from 'fs'
1313

1414
let child: ChildProcess
15+
let retry = 10
1516

16-
export function startCore(): void {
17+
export async function startCore(): Promise<void> {
1718
const corePath = mihomoCorePath(getAppConfig().core ?? 'mihomo')
1819
grantCorePermition(corePath)
1920
generateProfile()
20-
checkProfile()
21+
await checkProfile()
2122
stopCore()
22-
child = spawn(corePath, ['-d', mihomoWorkDir()])
23-
child.stdout?.on('data', (data) => {
24-
fs.writeFileSync(
25-
logPath(),
26-
data
27-
.toString()
28-
.split('\n')
29-
.map((line: string) => {
30-
if (line) return `[Mihomo]: ${line}`
31-
return ''
32-
})
33-
.filter(Boolean)
34-
.join('\n'),
35-
{
36-
flag: 'a'
23+
return new Promise((resolve, reject) => {
24+
child = spawn(corePath, ['-d', mihomoWorkDir()])
25+
child.stdout?.on('data', (data) => {
26+
if (data.toString().includes('External controller listen error')) {
27+
if (retry) {
28+
retry--
29+
resolve(startCore())
30+
} else {
31+
dialog.showErrorBox('External controller listen error', data.toString())
32+
reject('External controller listen error')
33+
}
34+
}
35+
if (data.toString().includes('RESTful API listening at')) {
36+
retry = 10
37+
resolve()
38+
}
39+
fs.writeFileSync(
40+
logPath(),
41+
data
42+
.toString()
43+
.split('\n')
44+
.map((line: string) => {
45+
if (line) return `[Mihomo]: ${line}`
46+
return ''
47+
})
48+
.filter(Boolean)
49+
.join('\n'),
50+
{
51+
flag: 'a'
52+
}
53+
)
54+
})
55+
child.on('error', (err) => {
56+
if (retry) {
57+
retry--
58+
startCore()
59+
} else {
60+
dialog.showErrorBox('External controller listen error', err.toString())
61+
reject(err)
3762
}
38-
)
39-
})
40-
child.on('close', (code, signal) => {
41-
fs.writeFileSync(logPath(), `[Manager]: Core closed, code: ${code}, signal: ${signal}\n`, {
42-
flag: 'a'
4363
})
44-
fs.writeFileSync(logPath(), `[Manager]: Restart Core\n`, {
45-
flag: 'a'
64+
child.on('close', async (code, signal) => {
65+
fs.writeFileSync(logPath(), `[Manager]: Core closed, code: ${code}, signal: ${signal}\n`, {
66+
flag: 'a'
67+
})
68+
fs.writeFileSync(logPath(), `[Manager]: Restart Core\n`, {
69+
flag: 'a'
70+
})
71+
await startCore()
4672
})
47-
restartCore()
4873
})
4974
}
5075

5176
export function stopCore(): void {
5277
if (child) {
5378
child.removeAllListeners()
54-
child.kill('SIGINT')
79+
if (!child.kill('SIGINT')) {
80+
stopCore()
81+
}
5582
}
5683
}
5784

58-
export function restartCore(): void {
59-
startCore()
60-
}
61-
62-
export function checkProfile(): void {
85+
export function checkProfile(): Promise<void> {
6386
const corePath = mihomoCorePath(getAppConfig().core ?? 'mihomo')
64-
try {
65-
execFileSync(corePath, ['-t', '-f', mihomoWorkConfigPath(), '-d', mihomoTestDir()])
66-
} catch (e) {
67-
dialog.showErrorBox('Profile check failed', `${e}`)
68-
throw new Error('Profile check failed')
69-
}
87+
return new Promise((resolve, reject) => {
88+
const child = execFile(corePath, ['-t', '-f', mihomoWorkConfigPath(), '-d', mihomoTestDir()])
89+
child.stdout?.on('data', (data) => {
90+
data
91+
.toString()
92+
.split('\n')
93+
.forEach((line: string) => {
94+
if (line.includes('level=error')) {
95+
dialog.showErrorBox('Profile Check Failed', line.split('level=error')[1])
96+
reject(line)
97+
}
98+
})
99+
})
100+
child.on('close', (code) => {
101+
if (code === 0) {
102+
resolve()
103+
}
104+
})
105+
})
70106
}
71107

72108
export function grantCorePermition(corePath: string): void {

src/main/utils/ipc.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import {
2929
setProfileStr,
3030
updateProfileItem
3131
} from '../config'
32-
import { isEncryptionAvailable, restartCore } from '../core/manager'
32+
import { isEncryptionAvailable, startCore } from '../core/manager'
3333
import { triggerSysProxy } from '../resolve/sysproxy'
3434
import { checkUpdate } from '../resolve/autoUpdater'
3535

@@ -62,7 +62,7 @@ export function registerIpcMainHandlers(): void {
6262
ipcMain.handle('changeCurrentProfile', (_e, id) => changeCurrentProfile(id))
6363
ipcMain.handle('addProfileItem', (_e, item) => addProfileItem(item))
6464
ipcMain.handle('removeProfileItem', (_e, id) => removeProfileItem(id))
65-
ipcMain.handle('restartCore', restartCore)
65+
ipcMain.handle('restartCore', startCore)
6666
ipcMain.handle('triggerSysProxy', (_e, enable) => triggerSysProxy(enable))
6767
ipcMain.handle('isEncryptionAvailable', isEncryptionAvailable)
6868
ipcMain.handle('encryptString', (_e, str) => safeStorage.encryptString(str))

src/renderer/src/components/sider/mihomo-core-card.tsx.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,12 @@ const MihomoCoreCard: React.FC = () => {
5050
size="sm"
5151
variant="light"
5252
color="default"
53-
onPress={() => {
54-
restartCore()
53+
onPress={async () => {
54+
await restartCore()
55+
mutate()
56+
setTimeout(() => {
57+
mutate()
58+
}, 2000)
5559
}}
5660
>
5761
<IoMdRefresh className={`${match ? 'text-white' : 'text-foreground'} text-[24px]`} />

src/renderer/src/pages/proxies.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@ const Proxies: React.FC = () => {
1818
const { data: proxies, mutate } = useSWR('mihomoProxies', mihomoProxies)
1919
const { appConfig, patchAppConfig } = useAppConfig()
2020
const { proxyDisplayMode = 'simple', proxyDisplayOrder = 'default' } = appConfig || {}
21-
2221
const groups = useMemo(() => {
2322
const groups: IMihomoGroup[] = []
24-
if (proxies) {
23+
if (proxies && proxies.proxies && proxies.proxies['GLOBAL']) {
2524
const globalGroup = proxies.proxies['GLOBAL'] as IMihomoGroup
2625
for (const global of globalGroup.all) {
2726
if (isGroup(proxies.proxies[global])) {

0 commit comments

Comments
 (0)