@@ -2,6 +2,7 @@ use crate::lutris_cli::{self, GameData};
22use crate :: rustris_paths;
33use crate :: game_log_buffer:: LogBufferManager ;
44use std:: sync:: OnceLock ;
5+ use sysinfo:: { Pid , System } ;
56
67/// Global log buffer manager instance (like Lutris's LOG_BUFFERS)
78static LOG_BUFFERS : OnceLock < LogBufferManager > = OnceLock :: new ( ) ;
@@ -48,7 +49,6 @@ pub async fn launch_game_by_slug(slug: String, window: tauri::Window) -> Result<
4849 println ! ( "Closing Lutris GUI..." ) ;
4950
5051 // Use sysinfo to find and kill Lutris processes
51- use sysinfo:: System ;
5252 let mut sys = System :: new_all ( ) ;
5353 sys. refresh_all ( ) ;
5454
@@ -293,52 +293,34 @@ pub struct GameRunningStatus {
293293
294294#[ tauri:: command]
295295pub async fn check_game_running ( slug : String ) -> Result < GameRunningStatus , String > {
296- // Check if the game is running by looking for lutris running this specific game
297- use std:: process:: Command ;
298-
299296 println ! ( "Checking if game is running: {}" , slug) ;
300297
301- // Check if lutris itself is running this game
302- // This is the most reliable method since Lutris manages the game process
303- let pattern = format ! ( "lutris.*{}" , slug) ;
304- println ! ( " pgrep pattern: {}" , pattern) ;
305-
306- let lutris_check = Command :: new ( "pgrep" )
307- . arg ( "-f" )
308- . arg ( & pattern)
309- . output ( )
310- . map_err ( |e| format ! ( "Failed to run pgrep: {}" , e) ) ?;
311-
312- let is_running = lutris_check. status . success ( ) ;
313-
314- if is_running {
315- let stdout = String :: from_utf8_lossy ( & lutris_check. stdout ) ;
316- let pids: Vec < String > = stdout
317- . trim ( )
318- . split ( '\n' )
319- . map ( |s| s. trim ( ) . to_string ( ) )
320- . filter ( |s| !s. is_empty ( ) )
298+ // Use sysinfo to check for lutris processes running this game
299+ let mut sys = System :: new_all ( ) ;
300+ sys. refresh_all ( ) ;
301+
302+ let mut matching_pids = Vec :: new ( ) ;
303+
304+ for ( pid, process) in sys. processes ( ) {
305+ // Check command line for "lutris" and the game slug
306+ let cmd = process. cmd ( ) ;
307+ let cmd_string: Vec < String > = cmd. iter ( )
308+ . map ( |s| s. to_string_lossy ( ) . to_string ( ) )
321309 . collect ( ) ;
310+ let cmd_joined = cmd_string. join ( " " ) ;
322311
323- println ! ( " RUNNING - Found {} process(es)" , pids. len( ) ) ;
324-
325- // Show the actual command lines of matched processes
326- for pid in & pids {
327- if let Ok ( output) = Command :: new ( "ps" )
328- . arg ( "-p" )
329- . arg ( pid)
330- . arg ( "-o" )
331- . arg ( "cmd=" )
332- . output ( )
333- {
334- let cmd = String :: from_utf8_lossy ( & output. stdout ) ;
335- println ! ( " PID {}: {}" , pid, cmd. trim( ) ) ;
336- }
312+ if cmd_joined. contains ( "lutris" ) && cmd_joined. contains ( & slug) {
313+ let pid_string = pid. to_string ( ) ;
314+ println ! ( " Found process - PID {}: {}" , pid_string, cmd_joined) ;
315+ matching_pids. push ( pid_string) ;
337316 }
317+ }
338318
319+ if !matching_pids. is_empty ( ) {
320+ println ! ( " RUNNING - Found {} process(es)" , matching_pids. len( ) ) ;
339321 Ok ( GameRunningStatus {
340322 is_running : true ,
341- pids,
323+ pids : matching_pids ,
342324 } )
343325 } else {
344326 println ! ( " NOT RUNNING - No matching processes" ) ;
@@ -351,41 +333,29 @@ pub async fn check_game_running(slug: String) -> Result<GameRunningStatus, Strin
351333
352334#[ tauri:: command]
353335pub fn force_close_game ( pids : Vec < String > ) -> Result < ( ) , String > {
354- use std:: process:: Command ;
355-
356336 println ! ( "Force closing game processes: {:?}" , pids) ;
357337
358- for pid in pids {
359- println ! ( " Killing PID: {}" , pid ) ;
338+ let mut sys = System :: new_all ( ) ;
339+ sys . refresh_all ( ) ;
360340
361- // Try SIGTERM first (graceful)
362- let result = Command :: new ( "kill" )
363- . arg ( & pid)
364- . output ( ) ;
341+ for pid_string in pids {
342+ println ! ( " Killing PID: {}" , pid_string) ;
365343
366- match result {
367- Ok ( output) if output. status . success ( ) => {
368- println ! ( " Successfully sent SIGTERM to PID {}" , pid) ;
369- }
370- Ok ( _) => {
371- // If SIGTERM failed, try SIGKILL (force)
372- println ! ( " SIGTERM failed, trying SIGKILL for PID {}" , pid) ;
373- let kill_result = Command :: new ( "kill" )
374- . arg ( "-9" )
375- . arg ( & pid)
376- . output ( ) ;
377-
378- if let Ok ( output) = kill_result {
379- if output. status . success ( ) {
380- println ! ( " Successfully sent SIGKILL to PID {}" , pid) ;
381- } else {
382- println ! ( " Failed to kill PID {}" , pid) ;
383- }
344+ // Parse PID string to sysinfo Pid
345+ if let Ok ( pid_num) = pid_string. parse :: < usize > ( ) {
346+ let pid = Pid :: from_u32 ( pid_num as u32 ) ;
347+
348+ if let Some ( process) = sys. process ( pid) {
349+ if process. kill ( ) {
350+ println ! ( " Successfully killed PID {}" , pid_string) ;
351+ } else {
352+ println ! ( " Failed to kill PID {}" , pid_string) ;
384353 }
354+ } else {
355+ println ! ( " Process {} not found" , pid_string) ;
385356 }
386- Err ( e) => {
387- println ! ( " Error killing PID {}: {}" , pid, e) ;
388- }
357+ } else {
358+ println ! ( " Invalid PID: {}" , pid_string) ;
389359 }
390360 }
391361
0 commit comments