From f936bc02aea179bc9a0158d57f665df16d851fbf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Dec 2025 16:53:59 +0000 Subject: [PATCH 01/10] Initial plan From c34ddfa5638e7622ea8ee21c5f6576cf43dc9eea Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Dec 2025 17:07:31 +0000 Subject: [PATCH 02/10] Remove misleading boolean return from InterruptHandle::kill() Co-authored-by: jsturtevant <648372+jsturtevant@users.noreply.github.com> --- docs/cancellation.md | 1 - src/hyperlight_host/benches/benchmarks.rs | 2 +- src/hyperlight_host/src/hypervisor/mod.rs | 21 ++++++++++--------- src/hyperlight_host/src/metrics/mod.rs | 2 +- src/hyperlight_host/tests/integration_test.rs | 9 ++++---- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/docs/cancellation.md b/docs/cancellation.md index 459e3a35d..2b9dc8872 100644 --- a/docs/cancellation.md +++ b/docs/cancellation.md @@ -166,7 +166,6 @@ sequenceDiagram end deactivate IH - IH-->>Caller: sent_signal deactivate IH ``` diff --git a/src/hyperlight_host/benches/benchmarks.rs b/src/hyperlight_host/benches/benchmarks.rs index 70b0a0416..0858400f4 100644 --- a/src/hyperlight_host/benches/benchmarks.rs +++ b/src/hyperlight_host/benches/benchmarks.rs @@ -245,7 +245,7 @@ fn bench_guest_call_interrupt_latency(b: &mut criterion::Bencher, size: SandboxS // Small delay to ensure the guest function is running in VM before interrupting thread::sleep(std::time::Duration::from_millis(10)); let kill_start = Instant::now(); - assert!(interrupt_handle.kill()); + interrupt_handle.kill(); kill_start }); diff --git a/src/hyperlight_host/src/hypervisor/mod.rs b/src/hyperlight_host/src/hypervisor/mod.rs index 5cdd74b48..9f3a1da84 100644 --- a/src/hyperlight_host/src/hypervisor/mod.rs +++ b/src/hyperlight_host/src/hypervisor/mod.rs @@ -208,12 +208,13 @@ pub(crate) trait InterruptHandleImpl: InterruptHandle { pub trait InterruptHandle: Send + Sync + Debug { /// Interrupt the corresponding sandbox from running. /// - /// - If this is called while the the sandbox currently executing a guest function call, it will interrupt the sandbox and return `true`. - /// - If this is called while the sandbox is not running (for example before or after calling a guest function), it will do nothing and return `false`. + /// This method sets a cancellation flag that prevents or stops the execution of guest code: + /// - If called while the sandbox is currently executing a guest function, it will interrupt the vCPU. + /// - If called before the sandbox starts executing (e.g., before a guest function call), it will prevent execution from starting. /// /// # Note /// This function will block for the duration of the time it takes for the vcpu thread to be interrupted. - fn kill(&self) -> bool; + fn kill(&self); /// Used by a debugger to interrupt the corresponding sandbox from running. /// @@ -374,13 +375,13 @@ impl InterruptHandleImpl for LinuxInterruptHandle { #[cfg(any(kvm, mshv3))] impl InterruptHandle for LinuxInterruptHandle { - fn kill(&self) -> bool { + fn kill(&self) { // Release ordering ensures that any writes before kill() are visible to the vcpu thread // when it checks is_cancelled() with Acquire ordering self.state.fetch_or(Self::CANCEL_BIT, Ordering::Release); // Send signals to interrupt the vcpu if it's currently running - self.send_signal() + self.send_signal(); } #[cfg(gdb)] @@ -513,7 +514,7 @@ impl InterruptHandleImpl for WindowsInterruptHandle { #[cfg(target_os = "windows")] impl InterruptHandle for WindowsInterruptHandle { - fn kill(&self) -> bool { + fn kill(&self) { use windows::Win32::System::Hypervisor::WHvCancelRunVirtualProcessor; // Release ordering ensures that any writes before kill() are visible to the vcpu thread @@ -524,7 +525,7 @@ impl InterruptHandle for WindowsInterruptHandle { // This ensures we see the running state set by the vcpu thread let state = self.state.load(Ordering::Acquire); if state & Self::RUNNING_BIT == 0 { - return false; + return; } // Take read lock to prevent race with WHvDeletePartition in set_dropped(). @@ -534,15 +535,15 @@ impl InterruptHandle for WindowsInterruptHandle { Ok(guard) => guard, Err(e) => { log::error!("Failed to acquire partition_state read lock: {}", e); - return false; + return; } }; if guard.dropped { - return false; + return; } - unsafe { WHvCancelRunVirtualProcessor(guard.handle, 0, 0).is_ok() } + unsafe { WHvCancelRunVirtualProcessor(guard.handle, 0, 0).ok() }; } #[cfg(gdb)] fn kill_from_debugger(&self) -> bool { diff --git a/src/hyperlight_host/src/metrics/mod.rs b/src/hyperlight_host/src/metrics/mod.rs index a2228c8fc..eadd89303 100644 --- a/src/hyperlight_host/src/metrics/mod.rs +++ b/src/hyperlight_host/src/metrics/mod.rs @@ -118,7 +118,7 @@ mod tests { // interrupt the guest function call to "Spin" after 1 second let thread = thread::spawn(move || { thread::sleep(Duration::from_secs(1)); - assert!(interrupt_handle.kill()); + interrupt_handle.kill(); }); multi diff --git a/src/hyperlight_host/tests/integration_test.rs b/src/hyperlight_host/tests/integration_test.rs index c5e2d2a8a..c6c7e9399 100644 --- a/src/hyperlight_host/tests/integration_test.rs +++ b/src/hyperlight_host/tests/integration_test.rs @@ -87,7 +87,7 @@ fn interrupt_in_progress_guest_call() { // kill vm after 1 second let thread = thread::spawn(move || { thread::sleep(Duration::from_secs(1)); - assert!(interrupt_handle.kill()); + interrupt_handle.kill(); barrier2.wait(); // wait here until main thread has returned from the interrupted guest call barrier2.wait(); // wait here until main thread has dropped the sandbox assert!(interrupt_handle.dropped()); @@ -122,7 +122,7 @@ fn interrupt_guest_call_in_advance() { // kill vm before the guest call has started let thread = thread::spawn(move || { - assert!(!interrupt_handle.kill()); // should return false since vcpu is not running yet + interrupt_handle.kill(); barrier2.wait(); barrier2.wait(); // wait here until main thread has dropped the sandbox assert!(interrupt_handle.dropped()); @@ -274,10 +274,9 @@ fn interrupt_moved_sandbox() { let thread2 = thread::spawn(move || { barrier.wait(); thread::sleep(Duration::from_secs(1)); - assert!(interrupt_handle.kill()); + interrupt_handle.kill(); - // make sure this returns true, which means the sandbox wasn't killed incorrectly before - assert!(interrupt_handle2.kill()); + interrupt_handle2.kill(); }); let res = sbox2.call::("Spin", ()).unwrap_err(); From c8e471e9c924ed8836b646b760f69fd73bf04c24 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Dec 2025 17:19:59 +0000 Subject: [PATCH 03/10] Add error logging for WHvCancelRunVirtualProcessor failure Co-authored-by: jsturtevant <648372+jsturtevant@users.noreply.github.com> --- src/hyperlight_host/src/hypervisor/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/hyperlight_host/src/hypervisor/mod.rs b/src/hyperlight_host/src/hypervisor/mod.rs index 9f3a1da84..d6716a47d 100644 --- a/src/hyperlight_host/src/hypervisor/mod.rs +++ b/src/hyperlight_host/src/hypervisor/mod.rs @@ -543,7 +543,11 @@ impl InterruptHandle for WindowsInterruptHandle { return; } - unsafe { WHvCancelRunVirtualProcessor(guard.handle, 0, 0).ok() }; + unsafe { + if let Err(e) = WHvCancelRunVirtualProcessor(guard.handle, 0, 0) { + log::error!("Failed to cancel running virtual processor: {}", e); + } + }; } #[cfg(gdb)] fn kill_from_debugger(&self) -> bool { From 5350a8c1620a670082291d7401255418312ab972 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:04:15 +0000 Subject: [PATCH 04/10] Update kill() documentation to accurately describe timing behavior The documentation now clarifies that kill() effectiveness depends on when it's called relative to clear_cancel() in the guest function call lifecycle. Co-authored-by: ludfjig <4257730+ludfjig@users.noreply.github.com> --- src/hyperlight_host/src/hypervisor/mod.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/hyperlight_host/src/hypervisor/mod.rs b/src/hyperlight_host/src/hypervisor/mod.rs index d6716a47d..0a930424d 100644 --- a/src/hyperlight_host/src/hypervisor/mod.rs +++ b/src/hyperlight_host/src/hypervisor/mod.rs @@ -208,9 +208,15 @@ pub(crate) trait InterruptHandleImpl: InterruptHandle { pub trait InterruptHandle: Send + Sync + Debug { /// Interrupt the corresponding sandbox from running. /// - /// This method sets a cancellation flag that prevents or stops the execution of guest code: - /// - If called while the sandbox is currently executing a guest function, it will interrupt the vCPU. - /// - If called before the sandbox starts executing (e.g., before a guest function call), it will prevent execution from starting. + /// This method sets a cancellation flag that prevents or stops the execution of guest code. + /// The effectiveness of this call depends on timing relative to the guest function call lifecycle: + /// + /// - **Before guest call starts** (before `clear_cancel()` in `MultiUseSandbox::call()`): + /// The cancellation request will be cleared and ignored. + /// - **After guest call starts but before entering guest code** (after `clear_cancel()`, before `run_vcpu()`): + /// Will prevent the guest from executing. + /// - **While executing guest code**: Will interrupt the vCPU. + /// - **After guest call completes**: Has no effect (cancellation is cleared at the start of the next call). /// /// # Note /// This function will block for the duration of the time it takes for the vcpu thread to be interrupted. From ad4591d0552c1b5f33473c60784d3a7e594bc0a8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Dec 2025 20:49:20 +0000 Subject: [PATCH 05/10] Make tracing-tracy optional to fix gdb test build failures The tracing-tracy dependency was causing linker errors in CI due to glibc version incompatibility. Made it optional by: - Moving tracing-tracy from dev-dependencies to optional dependencies - Creating a new trace_tracy feature - Adding required-features to the tracing-tracy example This prevents tracy from being built during gdb tests, avoiding the linker error with __isoc23_fscanf and __isoc23_strtol symbols. Co-authored-by: jsturtevant <648372+jsturtevant@users.noreply.github.com> --- src/hyperlight_host/Cargo.toml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/hyperlight_host/Cargo.toml b/src/hyperlight_host/Cargo.toml index 8cd0ef944..51162947a 100644 --- a/src/hyperlight_host/Cargo.toml +++ b/src/hyperlight_host/Cargo.toml @@ -40,6 +40,7 @@ tracing = { version = "0.1.43", features = ["log"] } tracing-log = "0.2.0" tracing-core = "0.1.35" tracing-opentelemetry = { version = "0.32.0", optional = true } +tracing-tracy = { version = "0.11.4", optional = true } hyperlight-common = { workspace = true, default-features = true, features = [ "std" ] } hyperlight-guest-tracing = { workspace = true, default-features = true, optional = true } vmm-sys-util = "0.15.0" @@ -104,7 +105,6 @@ criterion = "0.8.1" tracing-chrome = "0.7.2" metrics-util = "0.20.1" metrics-exporter-prometheus = { version = "0.18.1", default-features = false } -tracing-tracy = "0.11.4" serde_json = "1.0" hyperlight-component-macro = { workspace = true } @@ -130,6 +130,7 @@ print_debug = [] # Dumps the VM state to a file on unexpected errors or crashes. The path of the file will be printed on stdout and logged. crashdump = ["dep:chrono"] trace_guest = ["dep:opentelemetry", "dep:tracing-opentelemetry", "dep:hyperlight-guest-tracing", "hyperlight-common/trace_guest"] +trace_tracy = ["dep:tracing-tracy"] mem_profile = [ "trace_guest", "dep:framehop", "dep:fallible-iterator", "hyperlight-common/mem_profile" ] kvm = ["dep:kvm-bindings", "dep:kvm-ioctls"] mshv3 = ["dep:mshv-bindings", "dep:mshv-ioctls"] @@ -139,6 +140,10 @@ fuzzing = ["hyperlight-common/fuzzing"] build-metadata = ["dep:built"] init-paging = [] +[[example]] +name = "tracing-tracy" +required-features = ["trace_tracy"] + [[bench]] name = "benchmarks" harness = false From 0daa0fdfa4de2eef97aa4f63269f47773cc808b5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 00:00:18 +0000 Subject: [PATCH 06/10] Restore boolean return value from InterruptHandle::kill() with improved docs Based on feedback, restored the boolean return value for kill() but updated the documentation to clarify what it means: - The boolean indicates whether a signal was sent, not whether cancellation succeeded - On Linux: true if signal was sent to vCPU thread, false if vCPU not running - On Windows: true if WHvCancelRunVirtualProcessor called successfully, false otherwise - A false return doesn't mean failure - the cancellation flag is always set Restored all test assertions that were checking the return value. Co-authored-by: jsturtevant <648372+jsturtevant@users.noreply.github.com> --- docs/cancellation.md | 1 + src/hyperlight_host/benches/benchmarks.rs | 2 +- src/hyperlight_host/src/hypervisor/mod.rs | 40 +++++++++++-------- src/hyperlight_host/src/metrics/mod.rs | 2 +- src/hyperlight_host/tests/integration_test.rs | 9 +++-- 5 files changed, 31 insertions(+), 23 deletions(-) diff --git a/docs/cancellation.md b/docs/cancellation.md index 2b9dc8872..459e3a35d 100644 --- a/docs/cancellation.md +++ b/docs/cancellation.md @@ -166,6 +166,7 @@ sequenceDiagram end deactivate IH + IH-->>Caller: sent_signal deactivate IH ``` diff --git a/src/hyperlight_host/benches/benchmarks.rs b/src/hyperlight_host/benches/benchmarks.rs index 0858400f4..70b0a0416 100644 --- a/src/hyperlight_host/benches/benchmarks.rs +++ b/src/hyperlight_host/benches/benchmarks.rs @@ -245,7 +245,7 @@ fn bench_guest_call_interrupt_latency(b: &mut criterion::Bencher, size: SandboxS // Small delay to ensure the guest function is running in VM before interrupting thread::sleep(std::time::Duration::from_millis(10)); let kill_start = Instant::now(); - interrupt_handle.kill(); + assert!(interrupt_handle.kill()); kill_start }); diff --git a/src/hyperlight_host/src/hypervisor/mod.rs b/src/hyperlight_host/src/hypervisor/mod.rs index 0a930424d..ec7e494f3 100644 --- a/src/hyperlight_host/src/hypervisor/mod.rs +++ b/src/hyperlight_host/src/hypervisor/mod.rs @@ -209,18 +209,20 @@ pub trait InterruptHandle: Send + Sync + Debug { /// Interrupt the corresponding sandbox from running. /// /// This method sets a cancellation flag that prevents or stops the execution of guest code. - /// The effectiveness of this call depends on timing relative to the guest function call lifecycle: /// - /// - **Before guest call starts** (before `clear_cancel()` in `MultiUseSandbox::call()`): - /// The cancellation request will be cleared and ignored. - /// - **After guest call starts but before entering guest code** (after `clear_cancel()`, before `run_vcpu()`): - /// Will prevent the guest from executing. - /// - **While executing guest code**: Will interrupt the vCPU. - /// - **After guest call completes**: Has no effect (cancellation is cleared at the start of the next call). + /// # Return Value + /// + /// The return value indicates whether a signal was sent to interrupt a running vCPU: + /// - On Linux: Returns `true` if a signal was sent to the vCPU thread, `false` if the vCPU was not running. + /// - On Windows: Returns `true` if `WHvCancelRunVirtualProcessor` was called successfully, `false` otherwise. + /// + /// **Important**: A return value of `false` does not mean the cancellation failed. The cancellation flag is + /// always set, which will prevent or stop execution. A `false` return simply means no signal was sent because + /// the vCPU was not actively running at that moment. /// /// # Note /// This function will block for the duration of the time it takes for the vcpu thread to be interrupted. - fn kill(&self); + fn kill(&self) -> bool; /// Used by a debugger to interrupt the corresponding sandbox from running. /// @@ -381,13 +383,13 @@ impl InterruptHandleImpl for LinuxInterruptHandle { #[cfg(any(kvm, mshv3))] impl InterruptHandle for LinuxInterruptHandle { - fn kill(&self) { + fn kill(&self) -> bool { // Release ordering ensures that any writes before kill() are visible to the vcpu thread // when it checks is_cancelled() with Acquire ordering self.state.fetch_or(Self::CANCEL_BIT, Ordering::Release); // Send signals to interrupt the vcpu if it's currently running - self.send_signal(); + self.send_signal() } #[cfg(gdb)] @@ -520,7 +522,7 @@ impl InterruptHandleImpl for WindowsInterruptHandle { #[cfg(target_os = "windows")] impl InterruptHandle for WindowsInterruptHandle { - fn kill(&self) { + fn kill(&self) -> bool { use windows::Win32::System::Hypervisor::WHvCancelRunVirtualProcessor; // Release ordering ensures that any writes before kill() are visible to the vcpu thread @@ -531,7 +533,7 @@ impl InterruptHandle for WindowsInterruptHandle { // This ensures we see the running state set by the vcpu thread let state = self.state.load(Ordering::Acquire); if state & Self::RUNNING_BIT == 0 { - return; + return false; } // Take read lock to prevent race with WHvDeletePartition in set_dropped(). @@ -541,19 +543,23 @@ impl InterruptHandle for WindowsInterruptHandle { Ok(guard) => guard, Err(e) => { log::error!("Failed to acquire partition_state read lock: {}", e); - return; + return false; } }; if guard.dropped { - return; + return false; } unsafe { - if let Err(e) = WHvCancelRunVirtualProcessor(guard.handle, 0, 0) { - log::error!("Failed to cancel running virtual processor: {}", e); + match WHvCancelRunVirtualProcessor(guard.handle, 0, 0) { + Ok(_) => true, + Err(e) => { + log::error!("Failed to cancel running virtual processor: {}", e); + false + } } - }; + } } #[cfg(gdb)] fn kill_from_debugger(&self) -> bool { diff --git a/src/hyperlight_host/src/metrics/mod.rs b/src/hyperlight_host/src/metrics/mod.rs index eadd89303..a2228c8fc 100644 --- a/src/hyperlight_host/src/metrics/mod.rs +++ b/src/hyperlight_host/src/metrics/mod.rs @@ -118,7 +118,7 @@ mod tests { // interrupt the guest function call to "Spin" after 1 second let thread = thread::spawn(move || { thread::sleep(Duration::from_secs(1)); - interrupt_handle.kill(); + assert!(interrupt_handle.kill()); }); multi diff --git a/src/hyperlight_host/tests/integration_test.rs b/src/hyperlight_host/tests/integration_test.rs index c6c7e9399..c5e2d2a8a 100644 --- a/src/hyperlight_host/tests/integration_test.rs +++ b/src/hyperlight_host/tests/integration_test.rs @@ -87,7 +87,7 @@ fn interrupt_in_progress_guest_call() { // kill vm after 1 second let thread = thread::spawn(move || { thread::sleep(Duration::from_secs(1)); - interrupt_handle.kill(); + assert!(interrupt_handle.kill()); barrier2.wait(); // wait here until main thread has returned from the interrupted guest call barrier2.wait(); // wait here until main thread has dropped the sandbox assert!(interrupt_handle.dropped()); @@ -122,7 +122,7 @@ fn interrupt_guest_call_in_advance() { // kill vm before the guest call has started let thread = thread::spawn(move || { - interrupt_handle.kill(); + assert!(!interrupt_handle.kill()); // should return false since vcpu is not running yet barrier2.wait(); barrier2.wait(); // wait here until main thread has dropped the sandbox assert!(interrupt_handle.dropped()); @@ -274,9 +274,10 @@ fn interrupt_moved_sandbox() { let thread2 = thread::spawn(move || { barrier.wait(); thread::sleep(Duration::from_secs(1)); - interrupt_handle.kill(); + assert!(interrupt_handle.kill()); - interrupt_handle2.kill(); + // make sure this returns true, which means the sandbox wasn't killed incorrectly before + assert!(interrupt_handle2.kill()); }); let res = sbox2.call::("Spin", ()).unwrap_err(); From 21cdb543052476321227dc05f7e1afe3a6a6bed4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 00:02:06 +0000 Subject: [PATCH 07/10] Improve unsafe block scope in Windows kill() implementation Narrowed the unsafe block to only wrap the unsafe function call, keeping the match expression outside for better code clarity. Co-authored-by: jsturtevant <648372+jsturtevant@users.noreply.github.com> --- src/hyperlight_host/src/hypervisor/mod.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/hyperlight_host/src/hypervisor/mod.rs b/src/hyperlight_host/src/hypervisor/mod.rs index ec7e494f3..183aa1c52 100644 --- a/src/hyperlight_host/src/hypervisor/mod.rs +++ b/src/hyperlight_host/src/hypervisor/mod.rs @@ -551,13 +551,12 @@ impl InterruptHandle for WindowsInterruptHandle { return false; } - unsafe { - match WHvCancelRunVirtualProcessor(guard.handle, 0, 0) { - Ok(_) => true, - Err(e) => { - log::error!("Failed to cancel running virtual processor: {}", e); - false - } + let result = unsafe { WHvCancelRunVirtualProcessor(guard.handle, 0, 0) }; + match result { + Ok(_) => true, + Err(e) => { + log::error!("Failed to cancel running virtual processor: {}", e); + false } } } From 28890e757b92991530fe08f4ad89b1b1dd301c9b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 00:23:06 +0000 Subject: [PATCH 08/10] Revert Cargo.toml changes to tracing-tracy Reverted changes to Cargo.toml that made tracing-tracy optional. The tracy dependency is now back to being a regular dev-dependency as it was originally. Co-authored-by: jsturtevant <648372+jsturtevant@users.noreply.github.com> --- src/hyperlight_host/Cargo.toml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/hyperlight_host/Cargo.toml b/src/hyperlight_host/Cargo.toml index 51162947a..8cd0ef944 100644 --- a/src/hyperlight_host/Cargo.toml +++ b/src/hyperlight_host/Cargo.toml @@ -40,7 +40,6 @@ tracing = { version = "0.1.43", features = ["log"] } tracing-log = "0.2.0" tracing-core = "0.1.35" tracing-opentelemetry = { version = "0.32.0", optional = true } -tracing-tracy = { version = "0.11.4", optional = true } hyperlight-common = { workspace = true, default-features = true, features = [ "std" ] } hyperlight-guest-tracing = { workspace = true, default-features = true, optional = true } vmm-sys-util = "0.15.0" @@ -105,6 +104,7 @@ criterion = "0.8.1" tracing-chrome = "0.7.2" metrics-util = "0.20.1" metrics-exporter-prometheus = { version = "0.18.1", default-features = false } +tracing-tracy = "0.11.4" serde_json = "1.0" hyperlight-component-macro = { workspace = true } @@ -130,7 +130,6 @@ print_debug = [] # Dumps the VM state to a file on unexpected errors or crashes. The path of the file will be printed on stdout and logged. crashdump = ["dep:chrono"] trace_guest = ["dep:opentelemetry", "dep:tracing-opentelemetry", "dep:hyperlight-guest-tracing", "hyperlight-common/trace_guest"] -trace_tracy = ["dep:tracing-tracy"] mem_profile = [ "trace_guest", "dep:framehop", "dep:fallible-iterator", "hyperlight-common/mem_profile" ] kvm = ["dep:kvm-bindings", "dep:kvm-ioctls"] mshv3 = ["dep:mshv-bindings", "dep:mshv-ioctls"] @@ -140,10 +139,6 @@ fuzzing = ["hyperlight-common/fuzzing"] build-metadata = ["dep:built"] init-paging = [] -[[example]] -name = "tracing-tracy" -required-features = ["trace_tracy"] - [[bench]] name = "benchmarks" harness = false From 8b7a60c04f27cd0f9fa6f41d73cf29ae565e85e8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 00:28:25 +0000 Subject: [PATCH 09/10] Remove error logging for WHvCancelRunVirtualProcessor failure Removed the error logging that was added for WHvCancelRunVirtualProcessor failures as requested. The method now simply returns the result of is_ok() without logging. Co-authored-by: jsturtevant <648372+jsturtevant@users.noreply.github.com> --- src/hyperlight_host/src/hypervisor/mod.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/hyperlight_host/src/hypervisor/mod.rs b/src/hyperlight_host/src/hypervisor/mod.rs index 183aa1c52..8411d09d3 100644 --- a/src/hyperlight_host/src/hypervisor/mod.rs +++ b/src/hyperlight_host/src/hypervisor/mod.rs @@ -551,14 +551,7 @@ impl InterruptHandle for WindowsInterruptHandle { return false; } - let result = unsafe { WHvCancelRunVirtualProcessor(guard.handle, 0, 0) }; - match result { - Ok(_) => true, - Err(e) => { - log::error!("Failed to cancel running virtual processor: {}", e); - false - } - } + unsafe { WHvCancelRunVirtualProcessor(guard.handle, 0, 0).is_ok() } } #[cfg(gdb)] fn kill_from_debugger(&self) -> bool { From 533f3a8e0f33291fc886e65b41b604473e358639 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Dec 2025 00:53:28 +0000 Subject: [PATCH 10/10] Improve kill() documentation with clearer structure Updated the documentation for InterruptHandle::kill() based on feedback to: - Use clearer language about canceling guest execution - Better explain the return value meaning - Separate platform-specific behavior into its own section - Remove technical details about signals in favor of user-focused description Co-authored-by: ludfjig <4257730+ludfjig@users.noreply.github.com> --- src/hyperlight_host/src/hypervisor/mod.rs | 25 +++++++++++------------ 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/hyperlight_host/src/hypervisor/mod.rs b/src/hyperlight_host/src/hypervisor/mod.rs index 8411d09d3..02956c449 100644 --- a/src/hyperlight_host/src/hypervisor/mod.rs +++ b/src/hyperlight_host/src/hypervisor/mod.rs @@ -206,22 +206,21 @@ pub(crate) trait InterruptHandleImpl: InterruptHandle { /// A trait for handling interrupts to a sandbox's vcpu pub trait InterruptHandle: Send + Sync + Debug { - /// Interrupt the corresponding sandbox from running. + /// Cancel guest execution in the corresponding sandbox. /// - /// This method sets a cancellation flag that prevents or stops the execution of guest code. + /// If a guest call is in progress, it will be cancelled and the guest function call + /// will return an error. If called before a guest call is made, it has no effect on + /// future guest calls. /// - /// # Return Value + /// # Returns + /// - `true` if a guest call was in progress and the vcpu was actively running. + /// - `false` otherwise (no guest call in progress, or guest call in progress but vcpu + /// not yet running). Any in-progress guest call will still be cancelled. /// - /// The return value indicates whether a signal was sent to interrupt a running vCPU: - /// - On Linux: Returns `true` if a signal was sent to the vCPU thread, `false` if the vCPU was not running. - /// - On Windows: Returns `true` if `WHvCancelRunVirtualProcessor` was called successfully, `false` otherwise. - /// - /// **Important**: A return value of `false` does not mean the cancellation failed. The cancellation flag is - /// always set, which will prevent or stop execution. A `false` return simply means no signal was sent because - /// the vCPU was not actively running at that moment. - /// - /// # Note - /// This function will block for the duration of the time it takes for the vcpu thread to be interrupted. + /// # Platform behavior + /// - **Linux**: If the vcpu is running, this function will block for the duration of + /// the time it takes for the vcpu thread to be interrupted. + /// - **Windows**: This function returns immediately after requesting cancellation. fn kill(&self) -> bool; /// Used by a debugger to interrupt the corresponding sandbox from running.