fix: Update server process handling for Windows and Unix systems
This commit is contained in:
parent
7dbc2c3af2
commit
01d49a4b28
@ -57,6 +57,8 @@ hmac = "0.12.1"
|
|||||||
sha2 = "0.10.9"
|
sha2 = "0.10.9"
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
libloading = "0.8.7"
|
libloading = "0.8.7"
|
||||||
|
thiserror = "2.0.12"
|
||||||
|
nix = "=0.30.1"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
libc = "0.2.172"
|
libc = "0.2.172"
|
||||||
@ -65,4 +67,3 @@ libc = "0.2.172"
|
|||||||
tauri-plugin-updater = "2"
|
tauri-plugin-updater = "2"
|
||||||
once_cell = "1.18"
|
once_cell = "1.18"
|
||||||
tauri-plugin-single-instance = { version = "2.0.0", features = ["deep-link"] }
|
tauri-plugin-single-instance = { version = "2.0.0", features = ["deep-link"] }
|
||||||
thiserror = "2.0.12"
|
|
||||||
|
|||||||
@ -7,6 +7,8 @@ use tauri::State; // Import Manager trait
|
|||||||
use thiserror;
|
use thiserror;
|
||||||
use tokio::process::Command;
|
use tokio::process::Command;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
use std::time::Duration;
|
||||||
|
use tokio::time::timeout;
|
||||||
|
|
||||||
use crate::core::state::AppState;
|
use crate::core::state::AppState;
|
||||||
|
|
||||||
@ -131,6 +133,10 @@ pub async fn load_llama_model(
|
|||||||
// Optional: Redirect stdio if needed (e.g., for logging within Jan)
|
// Optional: Redirect stdio if needed (e.g., for logging within Jan)
|
||||||
// command.stdout(Stdio::piped());
|
// command.stdout(Stdio::piped());
|
||||||
// command.stderr(Stdio::piped());
|
// command.stderr(Stdio::piped());
|
||||||
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
command.creation_flags(CREATE_NEW_PROCESS_GROUP);
|
||||||
|
}
|
||||||
|
|
||||||
// Spawn the child process
|
// Spawn the child process
|
||||||
let child = command.spawn().map_err(ServerError::Io)?;
|
let child = command.spawn().map_err(ServerError::Io)?;
|
||||||
@ -163,48 +169,70 @@ pub async fn unload_llama_model(
|
|||||||
pid: String,
|
pid: String,
|
||||||
state: State<'_, AppState>,
|
state: State<'_, AppState>,
|
||||||
) -> ServerResult<UnloadResult> {
|
) -> ServerResult<UnloadResult> {
|
||||||
let mut process_map = state.llama_server_process.lock().await;
|
let mut map = state.llama_server_process.lock().await;
|
||||||
match process_map.remove(&pid) {
|
if let Some(mut child) = map.remove(&pid) {
|
||||||
Some(mut child) => {
|
#[cfg(unix)]
|
||||||
log::info!("Terminating server process with PID: {}", pid);
|
{
|
||||||
|
use nix::sys::signal::{kill, Signal};
|
||||||
|
use nix::unistd::Pid;
|
||||||
|
|
||||||
// 1. Send the kill signal
|
if let Some(raw_pid) = child.id() {
|
||||||
if let Err(e) = child.kill().await {
|
let raw_pid = raw_pid as i32;
|
||||||
log::error!("Failed to send kill to server process: {}", e);
|
log::info!("Sending SIGTERM to PID {}", raw_pid);
|
||||||
return Ok(UnloadResult {
|
let _ = kill(Pid::from_raw(raw_pid), Signal::SIGTERM);
|
||||||
success: false,
|
|
||||||
error: Some(format!("kill failed: {}", e)),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Await its exit so the OS can reap it
|
match timeout(Duration::from_secs(5), child.wait()).await {
|
||||||
|
Ok(Ok(status)) => log::info!("Process exited gracefully: {}", status),
|
||||||
|
Ok(Err(e)) => log::error!("Error waiting after SIGTERM: {}", e),
|
||||||
|
Err(_) => {
|
||||||
|
log::warn!("SIGTERM timed out; sending SIGKILL to PID {}", raw_pid);
|
||||||
|
let _ = kill(Pid::from_raw(raw_pid), Signal::SIGKILL);
|
||||||
match child.wait().await {
|
match child.wait().await {
|
||||||
Ok(exit_status) => {
|
Ok(s) => log::info!("Force-killed process exited: {}", s),
|
||||||
log::info!("Server exited with: {}", exit_status);
|
Err(e) => log::error!("Error waiting after SIGKILL: {}", e),
|
||||||
Ok(UnloadResult {
|
|
||||||
success: true,
|
|
||||||
error: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("Error waiting for server process: {}", e);
|
|
||||||
Ok(UnloadResult {
|
|
||||||
success: false,
|
|
||||||
error: Some(format!("wait failed: {}", e)),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
|
||||||
log::warn!("No server with PID '{}' found to unload", pid);
|
|
||||||
Ok(UnloadResult {
|
|
||||||
success: true,
|
|
||||||
error: None,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
use windows_sys::Win32::System::Console::{GenerateConsoleCtrlEvent, CTRL_C_EVENT};
|
||||||
|
use windows_sys::Win32::Foundation::BOOL;
|
||||||
|
|
||||||
|
if let Some(raw_pid) = child.id() {
|
||||||
|
log::info!("Sending Ctrl-C to PID {}", raw_pid);
|
||||||
|
let ok: BOOL = unsafe { GenerateConsoleCtrlEvent(CTRL_C_EVENT, raw_pid) };
|
||||||
|
if ok == 0 {
|
||||||
|
log::error!("Failed to send Ctrl-C to PID {}", raw_pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
match timeout(Duration::from_secs(5), child.wait()).await {
|
||||||
|
Ok(Ok(status)) => log::info!("Process exited after Ctrl-C: {}", status),
|
||||||
|
Ok(Err(e)) => log::error!("Error waiting after Ctrl-C: {}", e),
|
||||||
|
Err(_) => {
|
||||||
|
log::warn!("Timed out; force-killing PID {}", raw_pid);
|
||||||
|
if let Err(e) = child.kill().await {
|
||||||
|
log::error!("Failed to kill process {}: {}", raw_pid, e);
|
||||||
|
return Ok(UnloadResult { success: false, error: Some(format!("kill failed: {}", e)) });
|
||||||
|
}
|
||||||
|
if let Ok(s) = child.wait().await {
|
||||||
|
log::info!("Process finally exited: {}", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(UnloadResult { success: true, error: None })
|
||||||
|
} else {
|
||||||
|
log::warn!("No server with PID '{}' found", pid);
|
||||||
|
Ok(UnloadResult { success: true, error: None })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// crypto
|
// crypto
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn generate_api_key(model_id: String, api_secret: String) -> Result<String, String> {
|
pub fn generate_api_key(model_id: String, api_secret: String) -> Result<String, String> {
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
mod core;
|
mod core;
|
||||||
|
use reqwest::Client;
|
||||||
use core::{
|
use core::{
|
||||||
cmd::get_jan_data_folder_path,
|
cmd::get_jan_data_folder_path,
|
||||||
setup::{self, setup_mcp},
|
setup::{self, setup_mcp},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user