@@ -53,7 +53,7 @@ use std::fs::{metadata, File, OpenOptions};
53
53
use std:: os:: unix:: io:: { AsRawFd , RawFd } ;
54
54
use std:: path:: PathBuf ;
55
55
use std:: result;
56
- use std:: sync:: atomic:: { AtomicBool , AtomicUsize , Ordering , ATOMIC_USIZE_INIT } ;
56
+ use std:: sync:: atomic:: { AtomicUsize , Ordering , ATOMIC_USIZE_INIT } ;
57
57
use std:: sync:: mpsc:: { channel, Receiver , Sender , TryRecvError } ;
58
58
use std:: sync:: { Arc , Barrier , RwLock } ;
59
59
use std:: thread;
@@ -75,7 +75,7 @@ use logger::{AppInfo, Level, LogOption, Metric, LOGGER, METRICS};
75
75
use memory_model:: { GuestAddress , GuestMemory } ;
76
76
use serde_json:: Value ;
77
77
pub 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 } ;
79
79
use vm_control:: VmResponse ;
80
80
use vmm_config:: boot_source:: { BootSourceConfig , BootSourceConfigError } ;
81
81
use vmm_config:: drive:: { BlockDeviceConfig , BlockDeviceConfigs , DriveError } ;
@@ -96,6 +96,15 @@ const WRITE_METRICS_PERIOD_SECONDS: u64 = 60;
96
96
static START_INSTANCE_REQUEST_TS : AtomicUsize = ATOMIC_USIZE_INIT ;
97
97
static START_INSTANCE_REQUEST_CPU_TS : AtomicUsize = ATOMIC_USIZE_INIT ;
98
98
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
+
99
108
/// Errors associated with the VMM internal logic. These errors cannot be generated by direct user
100
109
/// input, but can result from bad configuration of the host (for example if Firecracker doesn't
101
110
/// have permissions to open the KVM fd).
@@ -340,7 +349,6 @@ impl MaybeHandler {
340
349
}
341
350
342
351
struct EpollEvent < T : AsRawFd > {
343
- dispatch_index : u64 ,
344
352
fd : T ,
345
353
}
346
354
@@ -428,23 +436,7 @@ impl EpollContext {
428
436
. map_err ( Error :: EpollFd ) ?;
429
437
self . dispatch_table . push ( Some ( token) ) ;
430
438
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 } )
448
440
}
449
441
450
442
fn allocate_tokens ( & mut self , count : usize ) -> ( u64 , Sender < Box < EpollHandler > > ) {
@@ -528,7 +520,6 @@ struct Vmm {
528
520
// Guest VM core resources.
529
521
guest_memory : Option < GuestMemory > ,
530
522
kernel_config : Option < KernelConfig > ,
531
- kill_signaled : Option < Arc < AtomicBool > > ,
532
523
vcpu_handles : Option < Vec < thread:: JoinHandle < ( ) > > > ,
533
524
exit_evt : Option < EpollEvent < EventFd > > ,
534
525
vm : Vm ,
@@ -591,7 +582,6 @@ impl Vmm {
591
582
shared_info : api_shared_info,
592
583
guest_memory : None ,
593
584
kernel_config : None ,
594
- kill_signaled : None ,
595
585
vcpu_handles : None ,
596
586
exit_evt : None ,
597
587
vm,
@@ -910,9 +900,6 @@ impl Vmm {
910
900
self . vcpu_handles = Some ( Vec :: with_capacity ( vcpu_count as usize ) ) ;
911
901
// It is safe to unwrap since it's set just above.
912
902
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 ( ) ;
916
903
917
904
let vcpu_thread_barrier = Arc :: new ( Barrier :: new ( ( vcpu_count + 1 ) as usize ) ) ;
918
905
@@ -925,7 +912,6 @@ impl Vmm {
925
912
. as_ref ( )
926
913
. ok_or ( StartMicrovmError :: DeviceManager ) ?;
927
914
let mmio_bus = device_manager. bus . clone ( ) ;
928
- let kill_signaled = kill_signaled. clone ( ) ;
929
915
let vcpu_thread_barrier = vcpu_thread_barrier. clone ( ) ;
930
916
// If the lock is poisoned, it's OK to panic.
931
917
let vcpu_exit_evt = self
@@ -1050,10 +1036,6 @@ impl Vmm {
1050
1036
} ,
1051
1037
_ => ( ) ,
1052
1038
}
1053
-
1054
- if kill_signaled. load ( Ordering :: SeqCst ) {
1055
- break ;
1056
- }
1057
1039
}
1058
1040
1059
1041
// Nothing we need do for the success case.
@@ -1206,36 +1188,6 @@ impl Vmm {
1206
1188
fn stop ( & mut self , exit_code : i32 ) {
1207
1189
info ! ( "Vmm is stopping." ) ;
1208
1190
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
-
1239
1191
if let Err ( e) = self . epoll_context . disable_stdin_event ( ) {
1240
1192
warn ! ( "Cannot disable the STDIN event. {:?}" , e) ;
1241
1193
}
@@ -1294,7 +1246,7 @@ impl Vmm {
1294
1246
}
1295
1247
None => warn ! ( "leftover exit-evt in epollcontext!" ) ,
1296
1248
}
1297
- self . stop ( 0 ) ;
1249
+ self . stop ( FC_EXIT_CODE_OK as i32 ) ;
1298
1250
}
1299
1251
EpollDispatch :: Stdin => {
1300
1252
let mut out = [ 0u8 ; 64 ] ;
@@ -1834,11 +1786,11 @@ pub fn start_vmm_thread(
1834
1786
match vmm. run_control ( ) {
1835
1787
Ok ( ( ) ) => {
1836
1788
info ! ( "Gracefully terminated VMM control loop" ) ;
1837
- vmm. stop ( 0 )
1789
+ vmm. stop ( FC_EXIT_CODE_OK as i32 )
1838
1790
}
1839
1791
Err ( e) => {
1840
1792
error ! ( "Abruptly exited VMM control loop: {:?}" , e) ;
1841
- vmm. stop ( 1 )
1793
+ vmm. stop ( FC_EXIT_CODE_GENERIC_ERROR as i32 ) ;
1842
1794
}
1843
1795
}
1844
1796
} )
@@ -2278,16 +2230,13 @@ mod tests {
2278
2230
}
2279
2231
2280
2232
#[ test]
2281
- fn add_remove_event_test ( ) {
2233
+ fn add_event_test ( ) {
2282
2234
let mut ep = EpollContext :: new ( ) . unwrap ( ) ;
2283
2235
let evfd = EventFd :: new ( ) . unwrap ( ) ;
2284
2236
2285
2237
// adding new event should work
2286
2238
let epev = ep. add_event ( evfd, EpollDispatch :: Exit ) ;
2287
2239
assert ! ( epev. is_ok( ) ) ;
2288
-
2289
- // removing event should work
2290
- assert ! ( ep. remove_event( epev. unwrap( ) ) . is_ok( ) ) ;
2291
2240
}
2292
2241
2293
2242
#[ test]
@@ -2323,60 +2272,6 @@ mod tests {
2323
2272
* ep. dispatch_table[ idx] . as_ref( ) . unwrap( ) ,
2324
2273
EpollDispatch :: Exit
2325
2274
) ;
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( ) ) ;
2380
2275
}
2381
2276
2382
2277
#[ test]
0 commit comments