Skip to main content

flowey_lib_hvlite/
stop_test_igvm_agent_rpc_server.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Stop the test_igvm_agent_rpc_server after VMM tests complete.
5//!
6//! This node terminates any running test_igvm_agent_rpc_server.exe processes
7//! using taskkill. It should be run after VMM tests complete to clean up
8//! the background server process started by run_test_igvm_agent_rpc_server.
9//!
10//! This node supports Windows and running Windows binaries through WSL2.
11
12use flowey::node::prelude::*;
13
14flowey_request! {
15    pub struct Request {
16        /// Dependency to ensure this runs after tests complete
17        pub after_tests: ReadVar<SideEffect>,
18        /// Completion indicator - signals that the server has been stopped
19        pub done: WriteVar<SideEffect>,
20    }
21}
22
23new_simple_flow_node!(struct Node);
24
25impl SimpleFlowNode for Node {
26    type Request = Request;
27
28    fn imports(_ctx: &mut ImportCtx<'_>) {}
29
30    fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
31        let Request { after_tests, done } = request;
32
33        ctx.emit_rust_step("stopping test_igvm_agent_rpc_server", |ctx| {
34            after_tests.claim(ctx);
35            done.claim(ctx);
36            move |rt| stop_rpc_server(rt)
37        });
38
39        Ok(())
40    }
41}
42
43fn stop_rpc_server(rt: &mut RustRuntimeServices<'_>) -> anyhow::Result<()> {
44    if !matches!(rt.platform(), FlowPlatform::Windows)
45        && !flowey_lib_common::_util::running_in_wsl(rt)
46    {
47        anyhow::bail!("stop_test_igvm_agent_rpc_server only supports Windows or WSL2");
48    }
49
50    log::info!("stopping test_igvm_agent_rpc_server processes");
51
52    // Use taskkill to terminate any running instances
53    let output = std::process::Command::new("taskkill.exe")
54        .args(["/F", "/IM", "test_igvm_agent_rpc_server.exe"])
55        .output();
56
57    match output {
58        Ok(output) => {
59            let stdout = String::from_utf8_lossy(&output.stdout);
60            let stderr = String::from_utf8_lossy(&output.stderr);
61
62            if output.status.success() {
63                log::info!("test_igvm_agent_rpc_server terminated: {}", stdout.trim());
64            } else if stderr.contains("not found") || stdout.contains("not found") {
65                // Process wasn't running - that's fine
66                log::info!("test_igvm_agent_rpc_server was not running");
67            } else {
68                log::warn!(
69                    "taskkill returned non-zero: stdout={}, stderr={}",
70                    stdout.trim(),
71                    stderr.trim()
72                );
73            }
74        }
75        Err(e) => {
76            log::warn!("failed to run taskkill: {}", e);
77        }
78    }
79
80    Ok(())
81}