Skip to content

Commit cf17942

Browse files
alexandruagsandreim
authored andcommitted
freeze device emulation between pause and unpause
Signed-off-by: Alexandru Agache <[email protected]>
1 parent f20c639 commit cf17942

File tree

1 file changed

+30
-7
lines changed

1 file changed

+30
-7
lines changed

src/firecracker/src/api_server_adapter.rs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use utils::{
1919
eventfd::EventFd,
2020
};
2121
use vmm::{
22-
rpc_interface::{PrebootApiController, RuntimeApiController},
22+
rpc_interface::{PrebootApiController, RuntimeApiController, VmmAction},
2323
vmm_config::instance_info::InstanceInfo,
2424
vmm_config::machine_config::VmConfig,
2525
Vmm,
@@ -58,6 +58,15 @@ impl ApiServerAdapter {
5858
.expect("EventManager events driver fatal error");
5959
}
6060
}
61+
62+
fn handle_request(&mut self, req_action: VmmAction) {
63+
let response = self.controller.handle_request(req_action);
64+
// Send back the result.
65+
self.to_api
66+
.send(Box::new(response))
67+
.map_err(|_| ())
68+
.expect("one-shot channel closed");
69+
}
6170
}
6271
impl Subscriber for ApiServerAdapter {
6372
/// Handle a read event (EPOLLIN).
@@ -68,12 +77,26 @@ impl Subscriber for ApiServerAdapter {
6877
if source == self.api_event_fd.as_raw_fd() && event_set == EventSet::IN {
6978
match self.from_api.try_recv() {
7079
Ok(api_request) => {
71-
let response = self.controller.handle_request(*api_request);
72-
// Send back the result.
73-
self.to_api
74-
.send(Box::new(response))
75-
.map_err(|_| ())
76-
.expect("one-shot channel closed");
80+
let request_is_pause = *api_request == VmmAction::Pause;
81+
self.handle_request(*api_request);
82+
83+
// If the latest req is a pause request, temporarily switch to a mode where we
84+
// do blocking `recv`s on the `from_api` receiver in a loop, until we get
85+
// unpaused. The device emulation is implicitly paused since we do not
86+
// relinquish control to the event manager because we're not returning from
87+
// `process`.
88+
if request_is_pause {
89+
// This loop only attempts to process API requests, so things like the
90+
// metric flush timerfd handling are frozen as well.
91+
loop {
92+
let req = self.from_api.recv().expect("Error receiving API request.");
93+
let req_is_resume = *req == VmmAction::Resume;
94+
self.handle_request(*req);
95+
if req_is_resume {
96+
break;
97+
}
98+
}
99+
}
77100
}
78101
Err(TryRecvError::Empty) => {
79102
warn!("Got a spurious notification from api thread");

0 commit comments

Comments
 (0)