fix: failed to relaunch app to update (#3351)

This commit is contained in:
Louis 2024-08-12 23:35:58 +07:00 committed by GitHub
parent 03455a9180
commit fcaf98a2fa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 141 additions and 104 deletions

View File

@ -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
*/

View File

@ -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()
}
}

29
electron/utils/cortex.ts Normal file
View File

@ -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
}
}

97
electron/utils/process.ts Normal file
View File

@ -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.`)
})
}

View File

@ -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) {