Skip to content

Commit 7f54723

Browse files
committed
reduce scope of unsafe
1 parent c655dfb commit 7f54723

File tree

1 file changed

+36
-43
lines changed

1 file changed

+36
-43
lines changed

phd-tests/framework/src/test_vm/server.rs

+36-43
Original file line numberDiff line numberDiff line change
@@ -62,52 +62,45 @@ impl PropolisServer {
6262
let (server_stdout, server_stderr) =
6363
log_mode.get_handles(&data_dir, vm_name)?;
6464

65-
// In the normal course of events, dropping a `TestVm` will spawn a task
66-
// that takes ownership of its `PropolisServer` and then sends Propolis
67-
// client calls to gracefully stop the VM running in that server (if
68-
// there is one). This ensures (modulo any bugs in Propolis itself) that
69-
// any Propolis servers hosting a running VM will have a chance to
70-
// destroy their kernel VMMs before the servers themselves go away.
65+
let mut server_cmd = std::process::Command::new("pfexec");
66+
server_cmd
67+
.args([
68+
server_path.as_str(),
69+
"run",
70+
config_toml_path.as_str(),
71+
server_addr.to_string().as_str(),
72+
vnc_addr.to_string().as_str(),
73+
])
74+
.stdout(server_stdout)
75+
.stderr(server_stderr);
76+
77+
// Gracefully shutting down a Propolis server requires PHD to send an
78+
// instance stop request to the server before it is actually terminated.
79+
// This ensures that the server has a chance to clean up kernel VMM
80+
// resources. It's desirable for the server to do this and not PHD
81+
// because a failure to clean up VMMs on stop is a Propolis bug.
7182
//
72-
// The PHD runner tries to give VMs a chance to tear down gracefully on
73-
// Ctrl-C by installing a custom SIGINT handler and using it to tell
74-
// running test tasks to shut down instead of completing their tests.
75-
// This allows the tests' VMs to be dropped gracefully. The trouble is
76-
// that with no additional intervention, pressing Ctrl-C to interrupt a
77-
// PHD runner process will typically cause SIGINTs to be delivered to
78-
// every process in the foreground process group, including both the
79-
// runner and all its Propolis server children. This breaks the `TestVm`
80-
// cleanup logic: by the time the VM is cleaned up, its server process
81-
// is already gone (due to the signal), so its VMM can't be cleaned up.
83+
// The PHD runner sets up a SIGINT handler that tries to give the
84+
// framework an opportunity to issue these requests before the runner
85+
// exits. However, pressing Ctrl-C in a shell will typically broadcast
86+
// SIGINT to all of the processes in the foreground process's group, not
87+
// just to the foreground process itself. This means that a Ctrl-C press
88+
// will usually kill all of PHD's Propolis servers before the cleanup
89+
// logic can run.
8290
//
83-
// To get around this, spawn Propolis server processes with a pre-`exec`
84-
// hook that directs them to ignore SIGINT. They will still be killed
85-
// during `TestVm` cleanup, assuming that executes normally; if the
86-
// runner is rudely terminated after that, the server process is still
87-
// preserved for investigation (and can still be cleaned up by other
88-
// means, e.g. SIGKILL).
89-
//
90-
// Note that it's undesirable for PHD to try to clean up leaked kernel
91-
// VMMs itself: leaking a kernel VMM after gracefully stopping a
92-
// Propolis server VM indicates a Propolis server bug.
91+
// To avoid this problem, add a pre-`exec` hook that directs Propolis
92+
// servers to ignore SIGINT. On Ctrl-C, the runner will drop all active
93+
// `TestVm`s, and this drop path (if allowed to complete) will kill all
94+
// these processes.
95+
unsafe {
96+
server_cmd.pre_exec(move || {
97+
libc::signal(libc::SIGINT, libc::SIG_IGN);
98+
Ok(())
99+
});
100+
}
101+
93102
let server = PropolisServer {
94-
server: unsafe {
95-
std::process::Command::new("pfexec")
96-
.args([
97-
server_path.as_str(),
98-
"run",
99-
config_toml_path.as_str(),
100-
server_addr.to_string().as_str(),
101-
vnc_addr.to_string().as_str(),
102-
])
103-
.stdout(server_stdout)
104-
.stderr(server_stderr)
105-
.pre_exec(move || {
106-
libc::signal(libc::SIGINT, libc::SIG_IGN);
107-
Ok(())
108-
})
109-
.spawn()?
110-
},
103+
server: server_cmd.spawn()?,
111104
address: server_addr,
112105
};
113106

0 commit comments

Comments
 (0)