@@ -53,7 +53,7 @@ use std::fs::{metadata, File, OpenOptions};
5353use std:: os:: unix:: io:: { AsRawFd , RawFd } ;
5454use std:: path:: PathBuf ;
5555use std:: result;
56- use std:: sync:: atomic:: { AtomicBool , AtomicUsize , Ordering , ATOMIC_USIZE_INIT } ;
56+ use std:: sync:: atomic:: { AtomicUsize , Ordering , ATOMIC_USIZE_INIT } ;
5757use std:: sync:: mpsc:: { channel, Receiver , Sender , TryRecvError } ;
5858use std:: sync:: { Arc , Barrier , RwLock } ;
5959use std:: thread;
@@ -75,7 +75,7 @@ use logger::{AppInfo, Level, LogOption, Metric, LOGGER, METRICS};
7575use memory_model:: { GuestAddress , GuestMemory } ;
7676use serde_json:: Value ;
7777pub use sigsys_handler:: setup_sigsys_handler;
78- use sys_util:: { register_signal_handler, EventFd , Killable , Terminal } ;
78+ use sys_util:: { register_signal_handler, EventFd , Terminal } ;
7979use vm_control:: VmResponse ;
8080use vmm_config:: boot_source:: { BootSourceConfig , BootSourceConfigError } ;
8181use vmm_config:: drive:: { BlockDeviceConfig , BlockDeviceConfigs , DriveError } ;
@@ -96,6 +96,15 @@ const WRITE_METRICS_PERIOD_SECONDS: u64 = 60;
9696static START_INSTANCE_REQUEST_TS : AtomicUsize = ATOMIC_USIZE_INIT ;
9797static START_INSTANCE_REQUEST_CPU_TS : AtomicUsize = ATOMIC_USIZE_INIT ;
9898
99+ /// Success exit code.
100+ pub const FC_EXIT_CODE_OK : u8 = 0 ;
101+ /// Generic error exit code.
102+ pub const FC_EXIT_CODE_GENERIC_ERROR : u8 = 1 ;
103+ /// Generic exit code for an error considered not possible to occur if the program logic is sound.
104+ pub const FC_EXIT_CODE_UNEXPECTED_ERROR : u8 = 2 ;
105+ /// Firecracker was shut down after intercepting a restricted system call.
106+ pub const FC_EXIT_CODE_BAD_SYSCALL : u8 = 148 ;
107+
99108/// Errors associated with the VMM internal logic. These errors cannot be generated by direct user
100109/// input, but can result from bad configuration of the host (for example if Firecracker doesn't
101110/// have permissions to open the KVM fd).
@@ -340,7 +349,6 @@ impl MaybeHandler {
340349}
341350
342351struct EpollEvent < T : AsRawFd > {
343- dispatch_index : u64 ,
344352 fd : T ,
345353}
346354
@@ -428,23 +436,7 @@ impl EpollContext {
428436 . map_err ( Error :: EpollFd ) ?;
429437 self . dispatch_table . push ( Some ( token) ) ;
430438
431- Ok ( EpollEvent { dispatch_index, fd } )
432- }
433-
434- fn remove_event < T > ( & mut self , epoll_event : EpollEvent < T > ) -> Result < ( ) >
435- where
436- T : AsRawFd ,
437- {
438- epoll:: ctl (
439- self . epoll_raw_fd ,
440- epoll:: ControlOptions :: EPOLL_CTL_DEL ,
441- epoll_event. fd . as_raw_fd ( ) ,
442- epoll:: Event :: new ( epoll:: Events :: EPOLLIN , epoll_event. dispatch_index ) ,
443- )
444- . map_err ( Error :: EpollFd ) ?;
445- self . dispatch_table [ epoll_event. dispatch_index as usize ] = None ;
446-
447- Ok ( ( ) )
439+ Ok ( EpollEvent { fd } )
448440 }
449441
450442 fn allocate_tokens ( & mut self , count : usize ) -> ( u64 , Sender < Box < EpollHandler > > ) {
@@ -528,7 +520,6 @@ struct Vmm {
528520 // Guest VM core resources.
529521 guest_memory : Option < GuestMemory > ,
530522 kernel_config : Option < KernelConfig > ,
531- kill_signaled : Option < Arc < AtomicBool > > ,
532523 vcpu_handles : Option < Vec < thread:: JoinHandle < ( ) > > > ,
533524 exit_evt : Option < EpollEvent < EventFd > > ,
534525 vm : Vm ,
@@ -591,7 +582,6 @@ impl Vmm {
591582 shared_info : api_shared_info,
592583 guest_memory : None ,
593584 kernel_config : None ,
594- kill_signaled : None ,
595585 vcpu_handles : None ,
596586 exit_evt : None ,
597587 vm,
@@ -910,9 +900,6 @@ impl Vmm {
910900 self . vcpu_handles = Some ( Vec :: with_capacity ( vcpu_count as usize ) ) ;
911901 // It is safe to unwrap since it's set just above.
912902 let vcpu_handles = self . vcpu_handles . as_mut ( ) . unwrap ( ) ;
913- self . kill_signaled = Some ( Arc :: new ( AtomicBool :: new ( false ) ) ) ;
914- // It is safe to unwrap since it's set just above.
915- let kill_signaled = self . kill_signaled . as_mut ( ) . unwrap ( ) ;
916903
917904 let vcpu_thread_barrier = Arc :: new ( Barrier :: new ( ( vcpu_count + 1 ) as usize ) ) ;
918905
@@ -925,7 +912,6 @@ impl Vmm {
925912 . as_ref ( )
926913 . ok_or ( StartMicrovmError :: DeviceManager ) ?;
927914 let mmio_bus = device_manager. bus . clone ( ) ;
928- let kill_signaled = kill_signaled. clone ( ) ;
929915 let vcpu_thread_barrier = vcpu_thread_barrier. clone ( ) ;
930916 // If the lock is poisoned, it's OK to panic.
931917 let vcpu_exit_evt = self
@@ -1050,10 +1036,6 @@ impl Vmm {
10501036 } ,
10511037 _ => ( ) ,
10521038 }
1053-
1054- if kill_signaled. load ( Ordering :: SeqCst ) {
1055- break ;
1056- }
10571039 }
10581040
10591041 // Nothing we need do for the success case.
@@ -1206,36 +1188,6 @@ impl Vmm {
12061188 fn stop ( & mut self , exit_code : i32 ) {
12071189 info ! ( "Vmm is stopping." ) ;
12081190
1209- if let Some ( v) = self . kill_signaled . take ( ) {
1210- v. store ( true , Ordering :: SeqCst ) ;
1211- } ;
1212-
1213- if let Some ( handles) = self . vcpu_handles . take ( ) {
1214- for handle in handles {
1215- match handle. kill ( VCPU_RTSIG_OFFSET ) {
1216- Ok ( _) => {
1217- if let Err ( e) = handle. join ( ) {
1218- warn ! ( "Failed to join vcpu thread: {:?}" , e) ;
1219- METRICS . vcpu . failures . inc ( ) ;
1220- }
1221- }
1222- Err ( e) => {
1223- METRICS . vcpu . failures . inc ( ) ;
1224- warn ! ( "Failed to kill vcpu thread: {:?}" , e)
1225- }
1226- }
1227- }
1228- } ;
1229-
1230- if let Some ( evt) = self . exit_evt . take ( ) {
1231- if let Err ( e) = self . epoll_context . remove_event ( evt) {
1232- warn ! (
1233- "Cannot remove the exit event from the Epoll Context. {:?}" ,
1234- e
1235- ) ;
1236- }
1237- }
1238-
12391191 if let Err ( e) = self . epoll_context . disable_stdin_event ( ) {
12401192 warn ! ( "Cannot disable the STDIN event. {:?}" , e) ;
12411193 }
@@ -1294,7 +1246,7 @@ impl Vmm {
12941246 }
12951247 None => warn ! ( "leftover exit-evt in epollcontext!" ) ,
12961248 }
1297- self . stop ( 0 ) ;
1249+ self . stop ( FC_EXIT_CODE_OK as i32 ) ;
12981250 }
12991251 EpollDispatch :: Stdin => {
13001252 let mut out = [ 0u8 ; 64 ] ;
@@ -1834,11 +1786,11 @@ pub fn start_vmm_thread(
18341786 match vmm. run_control ( ) {
18351787 Ok ( ( ) ) => {
18361788 info ! ( "Gracefully terminated VMM control loop" ) ;
1837- vmm. stop ( 0 )
1789+ vmm. stop ( FC_EXIT_CODE_OK as i32 )
18381790 }
18391791 Err ( e) => {
18401792 error ! ( "Abruptly exited VMM control loop: {:?}" , e) ;
1841- vmm. stop ( 1 )
1793+ vmm. stop ( FC_EXIT_CODE_GENERIC_ERROR as i32 ) ;
18421794 }
18431795 }
18441796 } )
@@ -2278,16 +2230,13 @@ mod tests {
22782230 }
22792231
22802232 #[ test]
2281- fn add_remove_event_test ( ) {
2233+ fn add_event_test ( ) {
22822234 let mut ep = EpollContext :: new ( ) . unwrap ( ) ;
22832235 let evfd = EventFd :: new ( ) . unwrap ( ) ;
22842236
22852237 // adding new event should work
22862238 let epev = ep. add_event ( evfd, EpollDispatch :: Exit ) ;
22872239 assert ! ( epev. is_ok( ) ) ;
2288-
2289- // removing event should work
2290- assert ! ( ep. remove_event( epev. unwrap( ) ) . is_ok( ) ) ;
22912240 }
22922241
22932242 #[ test]
@@ -2323,60 +2272,6 @@ mod tests {
23232272 * ep. dispatch_table[ idx] . as_ref( ) . unwrap( ) ,
23242273 EpollDispatch :: Exit
23252274 ) ;
2326-
2327- // removing event should work
2328- assert ! ( ep. remove_event( epev) . is_ok( ) ) ;
2329- }
2330-
2331- #[ test]
2332- fn epoll_event_try_get_after_remove_test ( ) {
2333- let mut ep = EpollContext :: new ( ) . unwrap ( ) ;
2334- let evfd = EventFd :: new ( ) . unwrap ( ) ;
2335-
2336- // adding new event should work
2337- let epev = ep. add_event ( evfd, EpollDispatch :: Exit ) . unwrap ( ) ;
2338-
2339- let evpoll_events_len = 10 ;
2340-
2341- let mut events = vec ! [ epoll:: Event :: new( epoll:: Events :: empty( ) , 0 ) ; evpoll_events_len] ;
2342-
2343- // raise the event
2344- assert ! ( epev. fd. write( 1 ) . is_ok( ) ) ;
2345-
2346- // removing event should work
2347- assert ! ( ep. remove_event( epev) . is_ok( ) ) ;
2348-
2349- // epoll should have no pending events
2350- let epollret = epoll:: wait ( ep. epoll_raw_fd , 0 , & mut events[ ..] ) ;
2351- let num_events = epollret. unwrap ( ) ;
2352- assert_eq ! ( num_events, 0 ) ;
2353- }
2354-
2355- #[ test]
2356- fn epoll_event_try_use_after_remove_test ( ) {
2357- let mut ep = EpollContext :: new ( ) . unwrap ( ) ;
2358- let evfd = EventFd :: new ( ) . unwrap ( ) ;
2359-
2360- // adding new event should work
2361- let epev = ep. add_event ( evfd, EpollDispatch :: Exit ) . unwrap ( ) ;
2362-
2363- let evpoll_events_len = 10 ;
2364- let mut events = vec ! [ epoll:: Event :: new( epoll:: Events :: empty( ) , 0 ) ; evpoll_events_len] ;
2365-
2366- // raise the event
2367- assert ! ( epev. fd. write( 1 ) . is_ok( ) ) ;
2368-
2369- // epoll should report one event
2370- let epollret = epoll:: wait ( ep. epoll_raw_fd , 0 , & mut events[ ..] ) ;
2371- let num_events = epollret. unwrap ( ) ;
2372- assert_eq ! ( num_events, 1 ) ;
2373-
2374- // removing event should work
2375- assert ! ( ep. remove_event( epev) . is_ok( ) ) ;
2376-
2377- // reported event should no longer be available
2378- let idx = events[ 0 ] . data as usize ;
2379- assert ! ( ep. dispatch_table[ idx] . is_none( ) ) ;
23802275 }
23812276
23822277 #[ test]
0 commit comments