From a0cca6afbc6c63dc832043e3dc3d7b4dd3fe05b1 Mon Sep 17 00:00:00 2001 From: Caelan Sayler Date: Fri, 23 May 2025 21:04:35 +0100 Subject: [PATCH] Make process wait optional --- src/bins/src/commands/apply_windows_impl.rs | 2 +- src/bins/src/shared/util_common.rs | 4 +-- src/bins/src/windows/util.rs | 2 +- src/lib-rust/src/process_win.rs | 32 +++++++++++++++------ 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/bins/src/commands/apply_windows_impl.rs b/src/bins/src/commands/apply_windows_impl.rs index 57f711f8..3f77433e 100644 --- a/src/bins/src/commands/apply_windows_impl.rs +++ b/src/bins/src/commands/apply_windows_impl.rs @@ -58,7 +58,7 @@ pub fn apply_package_impl(old_locator: &VelopackLocator, package: &PathBuf, run_ let process_handle = process::run_process_as_admin(&exe_path, args, work_dir, false)?; info!("Waiting (up to 10 minutes) for elevated process to exit..."); - let result = process::wait_for_process_to_exit_with_timeout(process_handle, Duration::from_secs(10 * 60))?; + let result = process::wait_for_process_to_exit(process_handle, Some(Duration::from_secs(10 * 60)))?; info!("Elevated process has exited ({:?}).", result); return Ok(new_locator); } diff --git a/src/bins/src/shared/util_common.rs b/src/bins/src/shared/util_common.rs index 6cd5a48c..3a91665e 100644 --- a/src/bins/src/shared/util_common.rs +++ b/src/bins/src/shared/util_common.rs @@ -13,11 +13,11 @@ pub enum OperationWait { pub fn operation_wait(wait: OperationWait) { if let OperationWait::WaitPid(pid) = wait { - if let Err(e) = process::wait_for_pid_to_exit(pid, Duration::from_secs(60)) { + if let Err(e) = process::wait_for_pid_to_exit(pid, Some(Duration::from_secs(60))) { warn!("Failed to wait for process ({}) to exit ({}). Continuing...", pid, e); } } else if let OperationWait::WaitParent = wait { - if let Err(e) = process::wait_for_parent_to_exit(Duration::from_secs(60)) { + if let Err(e) = process::wait_for_parent_to_exit(Some(Duration::from_secs(60))) { warn!("Failed to wait for parent process to exit ({}). Continuing...", e); } } else { diff --git a/src/bins/src/windows/util.rs b/src/bins/src/windows/util.rs index f9dec71a..d6bd680e 100644 --- a/src/bins/src/windows/util.rs +++ b/src/bins/src/windows/util.rs @@ -40,7 +40,7 @@ pub fn run_hook(locator: &VelopackLocator, hook_name: &str, timeout_secs: u64) - let cmd = cmd.unwrap(); - match process::wait_for_process_to_exit_with_timeout(&cmd, Duration::from_secs(timeout_secs)) { + match process::wait_for_process_to_exit(&cmd, Some(Duration::from_secs(timeout_secs))) { Ok(WaitResult::NoWaitRequired) => { warn!("Was unable to wait for hook (it may have exited too quickly)."); } diff --git a/src/lib-rust/src/process_win.rs b/src/lib-rust/src/process_win.rs index fca094d0..f5fc0637 100644 --- a/src/lib-rust/src/process_win.rs +++ b/src/lib-rust/src/process_win.rs @@ -14,7 +14,7 @@ use windows::{ Security::{GetTokenInformation, TokenElevation, TOKEN_ELEVATION}, System::Threading::{ CreateProcessW, GetCurrentProcess, GetExitCodeProcess, GetProcessId, GetProcessTimes, OpenProcess, OpenProcessToken, - TerminateProcess, WaitForSingleObject, CREATE_NO_WINDOW, CREATE_UNICODE_ENVIRONMENT, PROCESS_ACCESS_RIGHTS, + TerminateProcess, WaitForSingleObject, CREATE_NO_WINDOW, CREATE_UNICODE_ENVIRONMENT, INFINITE, PROCESS_ACCESS_RIGHTS, PROCESS_BASIC_INFORMATION, PROCESS_QUERY_LIMITED_INFORMATION, PROCESS_SYNCHRONIZE, PROCESS_TERMINATE, STARTUPINFOW, STARTUPINFOW_FLAGS, }, @@ -394,14 +394,30 @@ pub enum WaitResult { NoWaitRequired, } -pub fn wait_for_process_to_exit_with_timeout>(process: T, dur: Duration) -> IoResult { +impl WaitResult { + pub fn code(&self) -> Option { + match self { + WaitResult::WaitTimeout => None, + WaitResult::ExitCode(c) => Some(*c), + WaitResult::NoWaitRequired => None, + } + } +} + +pub fn wait_for_process_to_exit>(process: T, dur: Option) -> IoResult { let process = *process.as_ref(); if process.is_invalid() { return Ok(WaitResult::NoWaitRequired); } - let ms = duration_to_ms(dur); - info!("Waiting {}ms for process handle to exit.", ms); + let ms = if let Some(dur) = dur { + let ms = duration_to_ms(dur); + info!("Waiting {}ms for process handle to exit.", ms); + ms + } else { + info!("Waiting indefinitely process handle to exit."); + INFINITE + }; unsafe { match WaitForSingleObject(process, ms) { @@ -416,13 +432,13 @@ pub fn wait_for_process_to_exit_with_timeout>(process: T, dur: } } -pub fn wait_for_pid_to_exit(pid: u32, dur: Duration) -> IoResult { +pub fn wait_for_pid_to_exit(pid: u32, dur: Option) -> IoResult { info!("Waiting for process pid-{} to exit.", pid); let handle = open_process(PROCESS_SYNCHRONIZE, false, pid)?; - wait_for_process_to_exit_with_timeout(handle, dur) + wait_for_process_to_exit(handle, dur) } -pub fn wait_for_parent_to_exit(dur: Duration) -> IoResult { +pub fn wait_for_parent_to_exit(dur: Option) -> IoResult { info!("Reading parent process information."); let basic_info = ProcessBasicInformation; let my_handle = unsafe { GetCurrentProcess() }; @@ -477,7 +493,7 @@ pub fn wait_for_parent_to_exit(dur: Duration) -> IoResult { } info!("Waiting for parent process ({}) to exit.", info.InheritedFromUniqueProcessId); - wait_for_process_to_exit_with_timeout(parent_handle, dur) + wait_for_process_to_exit(parent_handle, dur) } #[test]