Handle exit status correctly

This commit is contained in:
Tate, Hongliang Tian 2018-12-29 21:32:10 +08:00
parent e5d3ab3cf9
commit 05e5efdb57
6 changed files with 32 additions and 24 deletions

@ -49,10 +49,10 @@ pub extern "C" fn libos_boot(path_buf: *const i8) -> i32 {
backtrace::__rust_begin_short_backtrace(||{ backtrace::__rust_begin_short_backtrace(||{
match do_boot(&path_str) { match do_boot(&path_str) {
Ok(()) => 0, 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] #[no_mangle]
@ -61,13 +61,16 @@ pub extern "C" fn libos_run() -> i32 {
panic::catch_unwind(||{ panic::catch_unwind(||{
backtrace::__rust_begin_short_backtrace(||{ backtrace::__rust_begin_short_backtrace(||{
match do_run() { match do_run() {
Ok(()) => 0, Ok(exit_status) => exit_status,
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)
} }
// 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 // TODO: make sure do_boot can only be called once
fn do_boot(path_str: &str) -> Result<(), Error> { 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() // TODO: make sure do_run() cannot be called before do_boot()
fn do_run() -> Result<(), Error> { fn do_run() -> Result<i32, Error> {
process::run_task()?; let exit_status = process::run_task()?;
Ok(()) Ok(exit_status)
} }

@ -11,21 +11,21 @@ pub fn do_getpid() -> pid_t {
current_process.get_pid() current_process.get_pid()
} }
pub fn do_exit(exit_code: i32) { pub fn do_exit(exit_status: i32) {
let current_ref = get_current(); let current_ref = get_current();
let mut current_process = current_ref.lock().unwrap(); 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<i32, Error> { pub fn do_wait4(child_pid: u32) -> Result<i32, Error> {
let child_process = process_table::get(child_pid) let child_process = process_table::get(child_pid)
.ok_or_else(|| (Errno::ECHILD, "Cannot find child process with the given 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 { loop {
let guard = child_process.lock().unwrap(); let guard = child_process.lock().unwrap();
if guard.get_status() == Status::ZOMBIE { if guard.get_status() == Status::ZOMBIE {
exit_code = guard.get_exit_code(); exit_status = guard.get_exit_status();
break; break;
} }
drop(guard); drop(guard);
@ -34,7 +34,7 @@ pub fn do_wait4(child_pid: u32) -> Result<i32, Error> {
let child_pid = child_process.lock().unwrap().get_pid(); let child_pid = child_process.lock().unwrap().get_pid();
process_table::remove(child_pid); process_table::remove(child_pid);
Ok(exit_code) Ok(exit_status)
} }
mod task; mod task;

@ -12,7 +12,7 @@ pub struct Process {
status: Status, status: Status,
pid: pid_t, pid: pid_t,
tgid: pid_t, tgid: pid_t,
exit_code: i32, exit_status: i32,
exec_path: String, exec_path: String,
vm: ProcessVM, vm: ProcessVM,
file_table: FileTable, file_table: FileTable,
@ -31,7 +31,7 @@ impl Process {
pid: new_pid, pid: new_pid,
tgid: new_pid, tgid: new_pid,
exec_path: exec_path.to_owned(), exec_path: exec_path.to_owned(),
exit_code: 0, exit_status: 0,
vm: vm, vm: vm,
file_table: file_table, file_table: file_table,
})); }));
@ -43,15 +43,15 @@ impl Process {
pub fn get_pid(&self) -> pid_t { self.pid } pub fn get_pid(&self) -> pid_t { self.pid }
pub fn get_tgid(&self) -> pid_t { self.tgid } pub fn get_tgid(&self) -> pid_t { self.tgid }
pub fn get_status(&self) -> Status { self.status } 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_exec_path(&self) -> &str { &self.exec_path }
pub fn get_vm(&self) -> &ProcessVM { &self.vm } pub fn get_vm(&self) -> &ProcessVM { &self.vm }
pub fn get_vm_mut(&mut self) -> &mut ProcessVM { &mut 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(&self) -> &FileTable { &self.file_table }
pub fn get_files_mut(&mut self) -> &mut FileTable { &mut self.file_table } pub fn get_files_mut(&mut self) -> &mut FileTable { &mut self.file_table }
pub fn exit(&mut self, exit_code: i32) { pub fn exit(&mut self, exit_status: i32) {
self.exit_code = exit_code; self.exit_status = exit_status;
self.status = Status::ZOMBIE; self.status = Status::ZOMBIE;
} }
} }

@ -34,7 +34,7 @@ fn dequeue_task() -> Option<ProcessRef> {
} }
pub fn run_task() -> Result<(), Error> { pub fn run_task() -> Result<i32, Error> {
let new_process : ProcessRef = dequeue_task() let new_process : ProcessRef = dequeue_task()
.ok_or_else(|| (Errno::EAGAIN, "No new processes to run"))?; .ok_or_else(|| (Errno::EAGAIN, "No new processes to run"))?;
set_current(&new_process); set_current(&new_process);
@ -51,13 +51,18 @@ pub fn run_task() -> Result<(), Error> {
do_run_task(task); 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 // Init process does not have any parent, so it has to release itself
if pid == 1 { if pid == 1 {
process_table::remove(1); process_table::remove(1);
} }
reset_current(); reset_current();
Ok(()) Ok(exit_status)
} }

@ -370,12 +370,12 @@ pub extern "C" fn occlum_spawn(
} }
#[no_mangle] #[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 options: c_int/*, rusage: *mut Rusage*/) -> c_int
{ {
match process::do_wait4(child_pid as u32) { match process::do_wait4(child_pid as u32) {
Ok(exit_code) => unsafe { Ok(exit_status) => unsafe {
*_exit_code = exit_code; *_exit_status = exit_status;
0 0
} }
Err(e) => { Err(e) => {

@ -225,7 +225,7 @@ int SGX_CDECL main(int argc, char *argv[])
sgx_ret = libos_boot(global_eid, &status, executable_path); sgx_ret = libos_boot(global_eid, &status, executable_path);
if(sgx_ret != SGX_SUCCESS) { if(sgx_ret != SGX_SUCCESS) {
print_error_message(sgx_ret); print_error_message(sgx_ret);
return -1; return status;
} }
status = wait_all_tasks(); status = wait_all_tasks();