fix: Update Cargo.toml dependencies on Windows & fix Ctrl+C handling on Windows

This change updates the dependencies of the Cargo.toml file on Windows to include additional features from the `windows-sys` crate. The `CreateProcess flags like CREATE_NEW_PROCESS_GROUP` feature is now enabled to allow for proper process management.
The code now properly sends Ctrl+C to the llama process on Windows, and also includes error handling for when the Ctrl+C command fails. Additionally, it now uses the `Windows` API to kill the process when it times out, and properly handles the wait for the process to exit.
This commit is contained in:
Akarshan 2025-07-03 13:50:19 +05:30
parent c34291237f
commit 6ab7d37a08
No known key found for this signature in database
GPG Key ID: D75C9634A870665F
2 changed files with 26 additions and 10 deletions

View File

@ -62,7 +62,11 @@ nix = "=0.30.1"
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
libc = "0.2.172" libc = "0.2.172"
windows-sys = "0.60.2" windows-sys = { version = "0.60.2", features = [
"Win32_Foundation",
"Win32_System_Console",
"Win32_System_Threading" # for using CreateProcess flags like CREATE_NEW_PROCESS_GROUP
] }
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
tauri-plugin-updater = "2" tauri-plugin-updater = "2"

View File

@ -3,13 +3,13 @@ use hmac::{Hmac, Mac};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sha2::Sha256; use sha2::Sha256;
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Duration;
use sysinfo::{Pid, ProcessesToUpdate, System};
use tauri::State; // Import Manager trait use tauri::State; // Import Manager trait
use thiserror; use thiserror;
use tokio::process::Command; use tokio::process::Command;
use uuid::Uuid;
use std::time::Duration;
use tokio::time::timeout; use tokio::time::timeout;
use sysinfo::{Pid, ProcessesToUpdate, System}; use uuid::Uuid;
use crate::core::state::AppState; use crate::core::state::AppState;
@ -136,6 +136,8 @@ pub async fn load_llama_model(
// command.stderr(Stdio::piped()); // command.stderr(Stdio::piped());
#[cfg(all(windows, target_arch = "x86_64"))] #[cfg(all(windows, target_arch = "x86_64"))]
{ {
use std::os::windows::process::CommandExt;
const CREATE_NEW_PROCESS_GROUP: u32 = 0x0000_0200;
command.creation_flags(CREATE_NEW_PROCESS_GROUP); command.creation_flags(CREATE_NEW_PROCESS_GROUP);
} }
@ -199,12 +201,14 @@ pub async fn unload_llama_model(
#[cfg(all(windows, target_arch = "x86_64"))] #[cfg(all(windows, target_arch = "x86_64"))]
{ {
use windows_sys::Win32::System::Console::{GenerateConsoleCtrlEvent, CTRL_C_EVENT};
use windows_sys::Win32::Foundation::BOOL; use windows_sys::Win32::Foundation::BOOL;
use windows_sys::Win32::System::Console::{GenerateConsoleCtrlEvent, CTRL_C_EVENT};
if let Some(raw_pid) = child.id() { if let Some(raw_pid) = child.id() {
log::info!("Sending Ctrl-C to PID {}", raw_pid); log::info!("Sending Ctrl-C to PID {}", raw_pid);
let ok: BOOL = unsafe { GenerateConsoleCtrlEvent(CTRL_C_EVENT, raw_pid) }; let ok: BOOL = unsafe {
GenerateConsoleCtrlEvent(CTRL_C_EVENT, raw_pid as u32)
};
if ok == 0 { if ok == 0 {
log::error!("Failed to send Ctrl-C to PID {}", raw_pid); log::error!("Failed to send Ctrl-C to PID {}", raw_pid);
} }
@ -216,7 +220,10 @@ pub async fn unload_llama_model(
log::warn!("Timed out; force-killing PID {}", raw_pid); log::warn!("Timed out; force-killing PID {}", raw_pid);
if let Err(e) = child.kill().await { if let Err(e) = child.kill().await {
log::error!("Failed to kill process {}: {}", raw_pid, e); log::error!("Failed to kill process {}: {}", raw_pid, e);
return Ok(UnloadResult { success: false, error: Some(format!("kill failed: {}", e)) }); return Ok(UnloadResult {
success: false,
error: Some(format!("kill failed: {}", e)),
});
} }
if let Ok(s) = child.wait().await { if let Ok(s) = child.wait().await {
log::info!("Process finally exited: {}", s); log::info!("Process finally exited: {}", s);
@ -226,14 +233,19 @@ pub async fn unload_llama_model(
} }
} }
Ok(UnloadResult { success: true, error: None }) Ok(UnloadResult {
success: true,
error: None,
})
} else { } else {
log::warn!("No server with PID '{}' found", pid); log::warn!("No server with PID '{}' found", pid);
Ok(UnloadResult { success: true, error: None }) 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> {