diff --git a/src/libos/src/lib.rs b/src/libos/src/lib.rs index e07540f1..d4aa8785 100644 --- a/src/libos/src/lib.rs +++ b/src/libos/src/lib.rs @@ -49,10 +49,10 @@ pub extern "C" fn libos_boot(path_buf: *const i8) -> i32 { backtrace::__rust_begin_short_backtrace(||{ match do_boot(&path_str) { Ok(()) => 0, - Err(err) => err.errno.as_retval() /* Normal error */, + Err(err) => EXIT_STATUS_INTERNAL_ERROR, } }) - }).unwrap_or(-1 /* Fatal error */) + }).unwrap_or(EXIT_STATUS_INTERNAL_ERROR) } #[no_mangle] @@ -61,13 +61,16 @@ pub extern "C" fn libos_run() -> i32 { panic::catch_unwind(||{ backtrace::__rust_begin_short_backtrace(||{ match do_run() { - Ok(()) => 0, - Err(err) => err.errno.as_retval() /* Normal error */, + Ok(exit_status) => exit_status, + Err(err) => EXIT_STATUS_INTERNAL_ERROR, } }) - }).unwrap_or(-1 /* Fatal error */) + }).unwrap_or(EXIT_STATUS_INTERNAL_ERROR) } +// Use 127 as a special value to indicate internal error from libos, not from +// user programs, although it is completely ok for a user program to return 127. +const EXIT_STATUS_INTERNAL_ERROR : i32 = 127; // TODO: make sure do_boot can only be called once fn do_boot(path_str: &str) -> Result<(), Error> { @@ -81,7 +84,7 @@ fn do_boot(path_str: &str) -> Result<(), Error> { } // TODO: make sure do_run() cannot be called before do_boot() -fn do_run() -> Result<(), Error> { - process::run_task()?; - Ok(()) +fn do_run() -> Result { + let exit_status = process::run_task()?; + Ok(exit_status) } diff --git a/src/libos/src/process/mod.rs b/src/libos/src/process/mod.rs index 3a9a55b5..798cb0bc 100644 --- a/src/libos/src/process/mod.rs +++ b/src/libos/src/process/mod.rs @@ -11,21 +11,21 @@ pub fn do_getpid() -> pid_t { current_process.get_pid() } -pub fn do_exit(exit_code: i32) { +pub fn do_exit(exit_status: i32) { let current_ref = get_current(); let mut current_process = current_ref.lock().unwrap(); - current_process.exit(exit_code); + current_process.exit(exit_status); } pub fn do_wait4(child_pid: u32) -> Result { let child_process = process_table::get(child_pid) .ok_or_else(|| (Errno::ECHILD, "Cannot find child process with the given PID"))?; - let mut exit_code = 0; + let mut exit_status = 0; loop { let guard = child_process.lock().unwrap(); if guard.get_status() == Status::ZOMBIE { - exit_code = guard.get_exit_code(); + exit_status = guard.get_exit_status(); break; } drop(guard); @@ -34,7 +34,7 @@ pub fn do_wait4(child_pid: u32) -> Result { let child_pid = child_process.lock().unwrap().get_pid(); process_table::remove(child_pid); - Ok(exit_code) + Ok(exit_status) } mod task; diff --git a/src/libos/src/process/process.rs b/src/libos/src/process/process.rs index 73c1c96c..1ed30bb2 100644 --- a/src/libos/src/process/process.rs +++ b/src/libos/src/process/process.rs @@ -12,7 +12,7 @@ pub struct Process { status: Status, pid: pid_t, tgid: pid_t, - exit_code: i32, + exit_status: i32, exec_path: String, vm: ProcessVM, file_table: FileTable, @@ -31,7 +31,7 @@ impl Process { pid: new_pid, tgid: new_pid, exec_path: exec_path.to_owned(), - exit_code: 0, + exit_status: 0, vm: vm, file_table: file_table, })); @@ -43,15 +43,15 @@ impl Process { pub fn get_pid(&self) -> pid_t { self.pid } pub fn get_tgid(&self) -> pid_t { self.tgid } pub fn get_status(&self) -> Status { self.status } - pub fn get_exit_code(&self) -> i32 { self.exit_code } + pub fn get_exit_status(&self) -> i32 { self.exit_status } pub fn get_exec_path(&self) -> &str { &self.exec_path } pub fn get_vm(&self) -> &ProcessVM { &self.vm } pub fn get_vm_mut(&mut self) -> &mut ProcessVM { &mut self.vm } pub fn get_files(&self) -> &FileTable { &self.file_table } pub fn get_files_mut(&mut self) -> &mut FileTable { &mut self.file_table } - pub fn exit(&mut self, exit_code: i32) { - self.exit_code = exit_code; + pub fn exit(&mut self, exit_status: i32) { + self.exit_status = exit_status; self.status = Status::ZOMBIE; } } diff --git a/src/libos/src/process/task.rs b/src/libos/src/process/task.rs index cd41cda5..1c6f2557 100644 --- a/src/libos/src/process/task.rs +++ b/src/libos/src/process/task.rs @@ -34,7 +34,7 @@ fn dequeue_task() -> Option { } -pub fn run_task() -> Result<(), Error> { +pub fn run_task() -> Result { let new_process : ProcessRef = dequeue_task() .ok_or_else(|| (Errno::EAGAIN, "No new processes to run"))?; set_current(&new_process); @@ -51,13 +51,18 @@ pub fn run_task() -> Result<(), Error> { do_run_task(task); } + let exit_status = { + let mut process = new_process.lock().unwrap(); + process.get_exit_status() + }; + // Init process does not have any parent, so it has to release itself if pid == 1 { process_table::remove(1); } reset_current(); - Ok(()) + Ok(exit_status) } diff --git a/src/libos/src/syscall/mod.rs b/src/libos/src/syscall/mod.rs index 4848826b..399f1ac6 100644 --- a/src/libos/src/syscall/mod.rs +++ b/src/libos/src/syscall/mod.rs @@ -370,12 +370,12 @@ pub extern "C" fn occlum_spawn( } #[no_mangle] -pub extern "C" fn occlum_wait4(child_pid: c_int, _exit_code: *mut c_int, +pub extern "C" fn occlum_wait4(child_pid: c_int, _exit_status: *mut c_int, options: c_int/*, rusage: *mut Rusage*/) -> c_int { match process::do_wait4(child_pid as u32) { - Ok(exit_code) => unsafe { - *_exit_code = exit_code; + Ok(exit_status) => unsafe { + *_exit_status = exit_status; 0 } Err(e) => { diff --git a/src/pal/pal.c b/src/pal/pal.c index d11d5d8e..24353177 100644 --- a/src/pal/pal.c +++ b/src/pal/pal.c @@ -225,7 +225,7 @@ int SGX_CDECL main(int argc, char *argv[]) sgx_ret = libos_boot(global_eid, &status, executable_path); if(sgx_ret != SGX_SUCCESS) { print_error_message(sgx_ret); - return -1; + return status; } status = wait_all_tasks();