Skip to content

Commit 3fd72a3

Browse files
committed
refactor(core): Store PID of core binary in a dedicated PID file instead of app settings
1 parent f67058c commit 3fd72a3

File tree

17 files changed

+163
-148
lines changed

17 files changed

+163
-148
lines changed

frontend/src/App.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ envStore.setupEnv().then(async () => {
9090
await sleep(Math.max(0, 1000 - duration))
9191
9292
loading.value = false
93-
kernelApiStore.updateKernelState()
93+
kernelApiStore.updateCoreState()
9494
})
9595
</script>
9696

frontend/src/components/TitleBar.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ onUnmounted(() => window.removeEventListener('resize', onResize))
9191
@dblclick="WindowToggleMaximise"
9292
:class="isDarwin ? 'justify-center py-4 text-12' : 'text-14'"
9393
:style="{
94-
color: appSettingsStore.app.kernel.running ? 'var(--primary-color)' : 'var(--color)',
94+
color: kernelApiStore.running ? 'var(--primary-color)' : 'var(--color)',
9595
}"
9696
class="font-bold w-full h-full flex items-center"
9797
>

frontend/src/constant/kernel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { useEnvStore } from '@/stores'
1111

1212
export const CoreStopOutputKeyword = 'start initial compatible provider default'
1313
export const CoreWorkingDirectory = 'data/mihomo'
14+
export const CorePidFilePath = CoreWorkingDirectory + '/pid.txt'
1415
export const CoreConfigFilePath = CoreWorkingDirectory + '/config.yaml'
1516
export const CoreCacheFilePath = CoreWorkingDirectory + '/cache.db'
1617

frontend/src/hooks/useCoreBranch.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ export const useCoreBranch = (isAlpha = false) => {
5555
const kernelApiStore = useKernelApiStore()
5656

5757
const restartable = computed(() => {
58-
const { running, branch } = appSettings.app.kernel
59-
if (!running) return false
58+
const { branch } = appSettings.app.kernel
59+
if (!kernelApiStore.running) return false
6060
return localVersion.value && downloadCompleted.value && (branch === Branch.Alpha) === isAlpha
6161
})
6262

@@ -181,9 +181,9 @@ export const useCoreBranch = (isAlpha = false) => {
181181
}
182182

183183
const restartCore = async () => {
184-
if (!appSettings.app.kernel.running) return
184+
if (!kernelApiStore.running) return
185185
try {
186-
await kernelApiStore.restartKernel()
186+
await kernelApiStore.restartCore()
187187
downloadCompleted.value = false
188188
message.success('common.success')
189189
} catch (error: any) {
@@ -209,10 +209,10 @@ export const useCoreBranch = (isAlpha = false) => {
209209

210210
const doRollback = () => MoveFile(CoreBakFilePath, CoreFilePath)
211211

212-
const { running, branch } = appSettings.app.kernel
213-
const isCurrentRunning = running && (branch === Branch.Alpha) === isAlpha
212+
const { branch } = appSettings.app.kernel
213+
const isCurrentRunning = kernelApiStore.running && (branch === Branch.Alpha) === isAlpha
214214
if (isCurrentRunning) {
215-
await kernelApiStore.restartKernel(doRollback)
215+
await kernelApiStore.restartCore(doRollback)
216216
} else {
217217
await doRollback()
218218
}

frontend/src/stores/appSettings.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@ export const useAppSettingsStore = defineStore('app-settings', () => {
6464
kernel: {
6565
branch: Branch.Main,
6666
profile: '',
67-
pid: 0,
68-
running: false,
6967
autoClose: true,
7068
unAvailable: true,
7169
cardMode: true,
@@ -125,6 +123,13 @@ export const useAppSettingsStore = defineStore('app-settings', () => {
125123
if (!app.value.kernel.cardColumns) {
126124
app.value.kernel.cardColumns = DefaultCardColumns
127125
}
126+
// @ts-expect-error(Deprecated)
127+
if (app.value.kernel.running !== undefined) {
128+
// @ts-expect-error(Deprecated)
129+
delete app.value.kernel.running
130+
// @ts-expect-error(Deprecated)
131+
delete app.value.kernel.pid
132+
}
128133

129134
firstOpen = !!data
130135

@@ -201,13 +206,7 @@ export const useAppSettingsStore = defineStore('app-settings', () => {
201206
)
202207

203208
watch(
204-
[
205-
themeMode,
206-
() => app.value.color,
207-
() => app.value.lang,
208-
() => app.value.kernel.running,
209-
() => app.value.addPluginToMenu,
210-
],
209+
[themeMode, () => app.value.color, () => app.value.lang, () => app.value.addPluginToMenu],
211210
updateTrayMenus,
212211
)
213212

frontend/src/stores/kernelApi.ts

Lines changed: 87 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { defineStore } from 'pinia'
22
import { computed, ref, watch } from 'vue'
33

44
import { getConfigs, setConfigs, getProxies, getProviders, Api } from '@/api/kernel'
5-
import { ProcessInfo, KillProcess, ExecBackground } from '@/bridge'
6-
import { CoreStopOutputKeyword, CoreWorkingDirectory } from '@/constant'
5+
import { ProcessInfo, KillProcess, ExecBackground, ReadFile, WriteFile, RemoveFile } from '@/bridge'
6+
import { CorePidFilePath, CoreStopOutputKeyword, CoreWorkingDirectory } from '@/constant'
77
import { Branch } from '@/enums/app'
88
import {
99
useAppSettingsStore,
@@ -14,7 +14,6 @@ import {
1414
} from '@/stores'
1515
import {
1616
generateConfigFile,
17-
ignoredError,
1817
updateTrayMenus,
1918
getKernelFileName,
2019
WebSockets,
@@ -203,75 +202,95 @@ export const useKernelApiStore = defineStore('kernelApi', () => {
203202
}
204203

205204
/* Bridge API */
205+
const corePid = ref(-1)
206+
const running = ref(false)
206207
const loading = ref(false)
207-
const statusLoading = ref(true)
208+
const coreStateLoading = ref(true)
208209
let isCoreStartedByThisInstance = false
209-
let doneCoreStopped: (value: unknown) => void
210+
let coreStoppedResolver: (value: unknown) => void
210211
let coreStoppedPromise: Promise<unknown>
211-
let doneFirstCoreUpdate: (value: unknown) => void
212-
const firstCoreUpdatePromise = new Promise((r) => (doneFirstCoreUpdate = r))
213212

214-
const isKernelRunning = async (pid: number) => {
215-
return pid && (await ProcessInfo(pid)).startsWith('mihomo')
216-
}
217-
218-
const updateKernelState = async () => {
219-
appSettingsStore.app.kernel.running = !!(await ignoredError(
220-
isKernelRunning,
221-
appSettingsStore.app.kernel.pid,
222-
))
213+
const updateCoreState = async () => {
214+
corePid.value = Number(await ReadFile(CorePidFilePath).catch(() => -1))
215+
const processName = corePid.value === -1 ? '' : await ProcessInfo(corePid.value).catch(() => '')
216+
running.value = processName.startsWith('mihomo')
223217

224-
if (!appSettingsStore.app.kernel.running) {
225-
appSettingsStore.app.kernel.pid = 0
226-
}
218+
coreStateLoading.value = false
227219

228-
statusLoading.value = false
229-
230-
if (appSettingsStore.app.kernel.running) {
220+
if (running.value) {
221+
initCoreWebsockets()
222+
longLivedWS.setup?.()
231223
await Promise.all([refreshConfig(), refreshProviderProxies()])
232224
await envStore.updateSystemProxyStatus()
233225
} else if (appSettingsStore.app.autoStartKernel) {
234-
await startKernel()
226+
await startCore()
235227
}
228+
}
236229

237-
doneFirstCoreUpdate(null)
230+
const runCoreProcess = (coreFilePath: string, args: string[], env: Recordable) => {
231+
return new Promise<number>((resolve) => {
232+
const pid = ExecBackground(
233+
coreFilePath,
234+
args,
235+
(out) => {
236+
logsStore.recordKernelLog(out)
237+
if (out.toLowerCase().includes(CoreStopOutputKeyword)) {
238+
resolve(pid)
239+
}
240+
},
241+
() => {
242+
onCoreStopped()
243+
resolve(0)
244+
},
245+
{ StopOutputKeyword: CoreStopOutputKeyword, Env: env },
246+
)
247+
})
238248
}
239249

240250
const onCoreStarted = async (pid: number) => {
241-
loading.value = false
242-
appSettingsStore.app.kernel.pid = pid
243-
appSettingsStore.app.kernel.running = true
251+
await WriteFile(CorePidFilePath, String(pid))
244252

253+
corePid.value = pid
254+
loading.value = false
255+
running.value = true
245256
isCoreStartedByThisInstance = true
246-
coreStoppedPromise = new Promise((r) => (doneCoreStopped = r))
257+
coreStoppedPromise = new Promise((r) => (coreStoppedResolver = r))
258+
247259
await Promise.all([refreshConfig(), refreshProviderProxies()])
248260

249261
if (appSettingsStore.app.autoSetSystemProxy) {
250262
await envStore.setSystemProxy().catch((err) => message.error(err))
251263
}
252264
await pluginsStore.onCoreStartedTrigger()
265+
266+
initCoreWebsockets()
267+
longLivedWS.setup?.()
253268
}
254269

255270
const onCoreStopped = async () => {
271+
await RemoveFile(CorePidFilePath)
272+
273+
corePid.value = -1
256274
loading.value = false
257-
appSettingsStore.app.kernel.pid = 0
258-
appSettingsStore.app.kernel.running = false
275+
running.value = false
259276

260277
if (appSettingsStore.app.autoSetSystemProxy) {
261278
await envStore.clearSystemProxy()
262279
}
263280
await pluginsStore.onCoreStoppedTrigger()
264281

265-
isCoreStartedByThisInstance && doneCoreStopped(null)
282+
isCoreStartedByThisInstance && coreStoppedResolver(null)
283+
284+
destroyCoreWebsockets()
266285
}
267286

268-
const startKernel = async () => {
287+
const startCore = async () => {
288+
if (running.value) throw 'The core is already running'
289+
269290
const { profile: profileID, branch } = appSettingsStore.app.kernel
270291
const profile = profilesStore.getProfileById(profileID)
271292
if (!profile) throw 'Choose a profile first'
272293

273-
await stopKernel()
274-
275294
const isAlpha = branch === Branch.Alpha
276295
const fileName = getKernelFileName(isAlpha)
277296
const kernelFilePath = CoreWorkingDirectory + '/' + fileName
@@ -282,43 +301,32 @@ export const useKernelApiStore = defineStore('kernelApi', () => {
282301
await generateConfigFile(profile, (config) =>
283302
pluginsStore.onBeforeCoreStartTrigger(config, profile),
284303
)
285-
const pid = await ExecBackground(
304+
const pid = await runCoreProcess(
286305
kernelFilePath,
287306
getKernelRuntimeArgs(isAlpha),
288-
(out) => {
289-
logsStore.recordKernelLog(out)
290-
if (out.toLowerCase().includes(CoreStopOutputKeyword)) {
291-
onCoreStarted(pid)
292-
}
293-
},
294-
onCoreStopped,
295-
{
296-
StopOutputKeyword: CoreStopOutputKeyword,
297-
Env: getKernelRuntimeEnv(isAlpha),
298-
},
307+
getKernelRuntimeEnv(isAlpha),
299308
)
309+
pid && (await onCoreStarted(pid))
300310
} catch (error) {
301311
loading.value = false
302312
throw error
303313
}
304314
}
305315

306-
const stopKernel = async () => {
307-
const { pid } = appSettingsStore.app.kernel
308-
const running = await ignoredError(isKernelRunning, pid)
309-
if (running) {
310-
await pluginsStore.onBeforeCoreStopTrigger()
311-
await KillProcess(pid)
312-
await (isCoreStartedByThisInstance ? coreStoppedPromise : onCoreStopped())
313-
}
316+
const stopCore = async () => {
317+
if (!running.value) throw 'The core is not running'
318+
319+
await pluginsStore.onBeforeCoreStopTrigger()
320+
await KillProcess(corePid.value)
321+
await (isCoreStartedByThisInstance ? coreStoppedPromise : onCoreStopped())
314322

315323
logsStore.clearKernelLog()
316324
}
317325

318-
const restartKernel = async (cleanupTask?: () => Promise<any>) => {
319-
await stopKernel()
326+
const restartCore = async (cleanupTask?: () => Promise<any>) => {
327+
await stopCore()
320328
await cleanupTask?.()
321-
await startKernel()
329+
await startCore()
322330
}
323331

324332
const getProxyPort = ():
@@ -364,28 +372,17 @@ export const useKernelApiStore = defineStore('kernelApi', () => {
364372
return source.concat([proxySignature, unAvailable, sortByDelay]).join('')
365373
})
366374

367-
watch(watchSources, updateTrayMenus)
368-
369-
watch(
370-
() => appSettingsStore.app.kernel.running,
371-
async (v) => {
372-
await firstCoreUpdatePromise
373-
if (v) {
374-
initCoreWebsockets()
375-
longLivedWS.setup?.()
376-
} else {
377-
destroyCoreWebsockets()
378-
}
379-
},
380-
)
375+
watch([watchSources, running], updateTrayMenus)
381376

382377
return {
383-
startKernel,
384-
stopKernel,
385-
restartKernel,
386-
updateKernelState,
378+
startCore,
379+
stopCore,
380+
restartCore,
381+
updateCoreState,
382+
pid: corePid,
383+
running,
387384
loading,
388-
statusLoading,
385+
coreStateLoading,
389386
config,
390387
proxies,
391388
providers,
@@ -398,5 +395,19 @@ export const useKernelApiStore = defineStore('kernelApi', () => {
398395
onMemory: createCoreWSHandlerRegister(websocketHandlers.memory),
399396
onTraffic: createCoreWSHandlerRegister(websocketHandlers.traffic),
400397
onConnections: createCoreWSHandlerRegister(websocketHandlers.connections),
398+
399+
// Deprecated
400+
startKernel: () => {
401+
console.warn('[Deprecated] "startKernel" is deprecated. Please use "startCore" instead.')
402+
startCore()
403+
},
404+
stopKernel: () => {
405+
console.warn('[Deprecated] "stopKernel" is deprecated. Please use "stopCore" instead.')
406+
stopCore()
407+
},
408+
restartKernel: (...args: any[]) => {
409+
console.warn('[Deprecated] "restartKernel" is deprecated. Please use "restartCore" instead.')
410+
restartCore(...args)
411+
},
401412
}
402413
})

frontend/src/types/app.d.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@ type AppSettings = {
6464
kernel: {
6565
branch: Branch
6666
profile: string
67-
pid: number
68-
running: boolean
6967
autoClose: boolean
7068
unAvailable: boolean
7169
cardMode: boolean

frontend/src/utils/command.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,18 @@ export const getCommands = () => {
5656
children: [
5757
{
5858
label: 'tray.startKernel',
59-
cmd: 'Start Kernel',
60-
handler: kernelStore.startKernel,
59+
cmd: 'Start Core',
60+
handler: kernelStore.startCore,
6161
},
6262
{
6363
label: 'tray.stopKernel',
64-
cmd: 'Stop Kernel',
65-
handler: kernelStore.stopKernel,
64+
cmd: 'Stop Core',
65+
handler: kernelStore.stopCore,
6666
},
6767
{
6868
label: 'tray.restartKernel',
69-
cmd: 'Restart Kernel',
70-
handler: kernelStore.restartKernel,
69+
cmd: 'Restart Core',
70+
handler: kernelStore.restartCore,
7171
},
7272
{
7373
label: 'tray.enableTunMode',

0 commit comments

Comments
 (0)