@@ -19,7 +19,7 @@ use utils::{
19
19
eventfd:: EventFd ,
20
20
} ;
21
21
use vmm:: {
22
- rpc_interface:: { PrebootApiController , RuntimeApiController } ,
22
+ rpc_interface:: { PrebootApiController , RuntimeApiController , VmmAction } ,
23
23
vmm_config:: instance_info:: InstanceInfo ,
24
24
vmm_config:: machine_config:: VmConfig ,
25
25
Vmm ,
@@ -58,6 +58,15 @@ impl ApiServerAdapter {
58
58
. expect ( "EventManager events driver fatal error" ) ;
59
59
}
60
60
}
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
+ }
61
70
}
62
71
impl Subscriber for ApiServerAdapter {
63
72
/// Handle a read event (EPOLLIN).
@@ -68,12 +77,26 @@ impl Subscriber for ApiServerAdapter {
68
77
if source == self . api_event_fd . as_raw_fd ( ) && event_set == EventSet :: IN {
69
78
match self . from_api . try_recv ( ) {
70
79
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
+ }
77
100
}
78
101
Err ( TryRecvError :: Empty ) => {
79
102
warn ! ( "Got a spurious notification from api thread" ) ;
0 commit comments