From 7658d284d049624de5ad2803969ad48e4035376c Mon Sep 17 00:00:00 2001 From: Louis Le Date: Mon, 12 Aug 2024 21:59:45 +0700 Subject: [PATCH] fix: failed to relaunch app to update --- electron/main.ts | 104 +----------------- electron/utils/clean.ts | 11 +- electron/utils/cortex.ts | 29 +++++ electron/utils/process.ts | 97 ++++++++++++++++ .../BottomPanel/SystemMonitor/index.tsx | 4 +- 5 files changed, 141 insertions(+), 104 deletions(-) create mode 100644 electron/utils/cortex.ts create mode 100644 electron/utils/process.ts diff --git a/electron/main.ts b/electron/main.ts index 2a94269a00..c346f8e713 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -1,7 +1,6 @@ import { app, BrowserWindow } from 'electron' import { join, resolve } from 'path' -import { execSync } from 'child_process' /** * Managers @@ -27,6 +26,7 @@ import { setupReactDevTool } from './utils/dev' import log from 'electron-log' import { start } from 'cortexso' +import { cortexCppPort, cortexJsPort, cortexHost, cleanCortexProcesses } from './utils/cortex' const preloadPath = join(__dirname, 'preload.js') const rendererPath = join(__dirname, '..', 'renderer') @@ -57,10 +57,6 @@ log.info('Starting jan from main thread..') // replace all console.log to log Object.assign(console, log.functions) -const cortexJsPort = 1338 -const cortexCppPort = 3940 -const host = '127.0.0.1' - app .whenReady() .then(() => { @@ -90,10 +86,9 @@ app } }) - .then(() => killProcessesOnPort(cortexCppPort)) - .then(() => killProcessesOnPort(cortexJsPort)) + .then(() => cleanCortexProcesses()) .then(() => { - start('jan', host, cortexJsPort, cortexCppPort, getJanDataFolderPath()) + start('jan', cortexHost, cortexJsPort, cortexCppPort, getJanDataFolderPath()) }) .then(createUserSpace) .then(migrate) @@ -126,20 +121,9 @@ app.once('quit', async () => { }) app.once('window-all-closed', async () => { - await stopApiServer() cleanUpAndQuit() }) -async function stopApiServer() { - // this function is not meant to be success. It will throw an error. - try { - await fetch(`http://${host}:${cortexJsPort}/v1/system`, { - method: 'DELETE', - }) - } catch (error) { - // do nothing - } -} /** * Handles various IPC messages from the renderer process. @@ -150,88 +134,6 @@ function handleIPCs() { handleAppIPCs() } -function killProcessesOnPort(port: number): void { - try { - console.log(`Killing processes on port ${port}...`) - if (process.platform === 'win32') { - killProcessesOnWindowsPort(port) - } else { - killProcessesOnUnixPort(port) - } - } catch (error) { - console.error( - `Failed to kill process(es) on port ${port}: ${(error as Error).message}` - ) - } -} - -function killProcessesOnWindowsPort(port: number): void { - let result: string - try { - result = execSync(`netstat -ano | findstr :${port}`).toString() - } catch (error) { - console.log(`No processes found on port ${port}.`) - return - } - - const lines = result.split('\n').filter(Boolean) - - if (lines.length === 0) { - console.log(`No processes found on port ${port}.`) - return - } - - const pids = lines - .map((line) => { - const parts = line.trim().split(/\s+/) - return parts[parts.length - 1] - }) - .filter((pid): pid is string => Boolean(pid) && !isNaN(Number(pid))) - - if (pids.length === 0) { - console.log(`No valid PIDs found for port ${port}.`) - return - } - const uniquePids = Array.from(new Set(pids)) - console.log('uniquePids', uniquePids) - - uniquePids.forEach((pid) => { - try { - execSync(`taskkill /PID ${pid} /F`) - console.log( - `Process with PID ${pid} on port ${port} has been terminated.` - ) - } catch (error) { - console.error( - `Failed to kill process with PID ${pid}: ${(error as Error).message}` - ) - } - }) -} - -function killProcessesOnUnixPort(port: number): void { - let pids: string[] - - try { - pids = execSync(`lsof -ti tcp:${port}`) - .toString() - .trim() - .split('\n') - .filter(Boolean) - } catch (error) { - if ((error as { status?: number }).status === 1) { - console.log(`No processes found on port ${port}.`) - return - } - throw error // Re-throw if it's not the "no processes found" error - } - - pids.forEach((pid) => { - process.kill(parseInt(pid), 'SIGTERM') - console.log(`Process with PID ${pid} on port ${port} has been terminated.`) - }) -} - /** * Suppress Node error messages */ diff --git a/electron/utils/clean.ts b/electron/utils/clean.ts index e7b7618fc5..9ca094876c 100644 --- a/electron/utils/clean.ts +++ b/electron/utils/clean.ts @@ -1,7 +1,14 @@ import { windowManager } from './../managers/window' import { app } from 'electron' +import { cleanCortexProcesses, stopCortexApiServer } from './cortex' -export function cleanUpAndQuit() { + +/** + * Clean up windows then quit + */ +export async function cleanUpAndQuit() { windowManager.cleanUp() + await stopCortexApiServer() + await cleanCortexProcesses() app.quit() -} +} \ No newline at end of file diff --git a/electron/utils/cortex.ts b/electron/utils/cortex.ts new file mode 100644 index 0000000000..afd2534c78 --- /dev/null +++ b/electron/utils/cortex.ts @@ -0,0 +1,29 @@ +import { killProcessesOnPort } from './process' + +// Cortex server configurations +export const cortexJsPort = 1338 +export const cortexCppPort = 3940 +export const cortexHost = '127.0.0.1' + +/** + * Kills all possible running cortex processes + */ +export async function cleanCortexProcesses() { + await killProcessesOnPort(cortexCppPort) + await killProcessesOnPort(cortexJsPort) +} + +/** + * Stops the cortex API server + */ +export async function stopCortexApiServer() { + // this function is not meant to be success. It will throw an error. + try { + await fetch(`http://${cortexHost}:${cortexJsPort}/v1/system`, { + method: 'DELETE', + }) + } catch (error) { + // Do nothing + // Accept failure here + } +} diff --git a/electron/utils/process.ts b/electron/utils/process.ts new file mode 100644 index 0000000000..90d9f49e46 --- /dev/null +++ b/electron/utils/process.ts @@ -0,0 +1,97 @@ +import { execSync } from 'child_process' + +/** + * Kill process on port util + * @param port port number to kill + */ +export function killProcessesOnPort(port: number): void { + try { + console.log(`Killing processes on port ${port}...`) + if (process.platform === 'win32') { + killProcessesOnWindowsPort(port) + } else { + killProcessesOnUnixPort(port) + } + } catch (error) { + console.error( + `Failed to kill process(es) on port ${port}: ${(error as Error).message}` + ) + } + } + +/** + * Kill process on port - Windows + * @param port + * @returns + */ +function killProcessesOnWindowsPort(port: number): void { + let result: string + try { + result = execSync(`netstat -ano | findstr :${port}`).toString() + } catch (error) { + console.log(`No processes found on port ${port}.`) + return + } + + const lines = result.split('\n').filter(Boolean) + + if (lines.length === 0) { + console.log(`No processes found on port ${port}.`) + return + } + + const pids = lines + .map((line) => { + const parts = line.trim().split(/\s+/) + return parts[parts.length - 1] + }) + .filter((pid): pid is string => Boolean(pid) && !isNaN(Number(pid))) + + if (pids.length === 0) { + console.log(`No valid PIDs found for port ${port}.`) + return + } + const uniquePids = Array.from(new Set(pids)) + console.log('uniquePids', uniquePids) + + uniquePids.forEach((pid) => { + try { + execSync(`taskkill /PID ${pid} /F`) + console.log( + `Process with PID ${pid} on port ${port} has been terminated.` + ) + } catch (error) { + console.error( + `Failed to kill process with PID ${pid}: ${(error as Error).message}` + ) + } + }) + } + + /** + * Kill process on port - Unix + * @param port + * @returns + */ + function killProcessesOnUnixPort(port: number): void { + let pids: string[] + + try { + pids = execSync(`lsof -ti tcp:${port}`) + .toString() + .trim() + .split('\n') + .filter(Boolean) + } catch (error) { + if ((error as { status?: number }).status === 1) { + console.log(`No processes found on port ${port}.`) + return + } + throw error // Re-throw if it's not the "no processes found" error + } + + pids.forEach((pid) => { + process.kill(parseInt(pid), 'SIGTERM') + console.log(`Process with PID ${pid} on port ${port} has been terminated.`) + }) + } \ No newline at end of file diff --git a/web/containers/Layout/BottomPanel/SystemMonitor/index.tsx b/web/containers/Layout/BottomPanel/SystemMonitor/index.tsx index 54c7bf7659..50c577c58a 100644 --- a/web/containers/Layout/BottomPanel/SystemMonitor/index.tsx +++ b/web/containers/Layout/BottomPanel/SystemMonitor/index.tsx @@ -65,7 +65,9 @@ const SystemMonitor: React.FC = () => { setCpuUsage(resourceEvent.cpu.usage) setGpus( resourceEvent.gpus?.filter( - (gpu) => gpu.name && gpu.vram.used && gpu.vram.total + // Do not check vram used here + // since it could count 0 case + (gpu) => gpu.name && gpu.vram.total ) ?? [] ) } catch (err) {