Fix thread exiting but not being freed
This commit is contained in:
parent
23329efe14
commit
a7400ca6dc
@ -15,6 +15,7 @@ unsafe impl Send for ChildProcessFilter {}
|
||||
pub fn do_exit(exit_status: i32) {
|
||||
let current_ref = get_current();
|
||||
let mut current = current_ref.lock().unwrap();
|
||||
let parent_ref = current.get_parent().clone();
|
||||
// Update current
|
||||
current.exit_status = exit_status;
|
||||
current.status = Status::ZOMBIE;
|
||||
@ -34,8 +35,15 @@ pub fn do_exit(exit_status: i32) {
|
||||
futex_wake(ctid as *const i32, 1);
|
||||
}
|
||||
|
||||
// If the process is detached, no need to notify the parent
|
||||
if current.is_detached {
|
||||
let current_tid = current.get_tid();
|
||||
drop(current);
|
||||
remove_zombie_child(&parent_ref, current_tid);
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify the parent process if necessary
|
||||
let parent_ref = current.get_parent().clone();
|
||||
let (mut parent, current) = {
|
||||
// Always lock parent before its child
|
||||
drop(current);
|
||||
@ -103,34 +111,44 @@ pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32) -> Res
|
||||
waiter
|
||||
};
|
||||
|
||||
// Wait until a child has interesting events
|
||||
let child_pid = waiter.sleep_until_woken_with_result();
|
||||
|
||||
let mut current = current_ref.lock().unwrap();
|
||||
let child_i = {
|
||||
let mut child_i_opt = None;
|
||||
for (child_i, child_ref) in current.get_children_iter().enumerate() {
|
||||
let child = child_ref.lock().unwrap();
|
||||
if child.get_pid() != child_pid {
|
||||
continue;
|
||||
}
|
||||
// Remove the child from the parent
|
||||
*exit_status = remove_zombie_child(¤t_ref, child_pid);
|
||||
|
||||
if child.get_status() != Status::ZOMBIE {
|
||||
panic!("THIS SHOULD NEVER HAPPEN!");
|
||||
}
|
||||
child_i_opt = Some(child_i);
|
||||
*exit_status = child.get_exit_status();
|
||||
}
|
||||
child_i_opt.unwrap()
|
||||
};
|
||||
current.children.swap_remove(child_i);
|
||||
let mut current = current_ref.lock().unwrap();
|
||||
current.waiting_children = None;
|
||||
|
||||
// Release the last reference to the child process
|
||||
process_table::remove(child_pid);
|
||||
|
||||
Ok(child_pid)
|
||||
}
|
||||
|
||||
fn remove_zombie_child(parent_ref: &ProcessRef, child_tid: pid_t) -> i32 {
|
||||
// Find the zombie child process
|
||||
let mut parent = parent_ref.lock().unwrap();
|
||||
let (child_i, child_ref) = parent
|
||||
.get_children_iter()
|
||||
.enumerate()
|
||||
.find(|(child_i, child_ref)| {
|
||||
let child = child_ref.lock().unwrap();
|
||||
if child.get_tid() != child_tid {
|
||||
return false;
|
||||
}
|
||||
assert!(child.get_status() == Status::ZOMBIE);
|
||||
true
|
||||
})
|
||||
.expect("cannot find the zombie child");
|
||||
|
||||
// Remove the zombie child from parent
|
||||
parent.children.swap_remove(child_i);
|
||||
// Remove the zombie child from process table
|
||||
process_table::remove(child_tid);
|
||||
|
||||
// Return the exit status
|
||||
let child = child_ref.lock().unwrap();
|
||||
child.get_exit_status()
|
||||
}
|
||||
|
||||
fn lock_two_in_order<'a>(
|
||||
first_ref: &'a ProcessRef,
|
||||
second_ref: &'a ProcessRef,
|
||||
|
@ -23,6 +23,7 @@ pub struct Process {
|
||||
tgid: pid_t,
|
||||
host_tid: pid_t,
|
||||
exit_status: i32,
|
||||
is_detached: bool,
|
||||
// TODO: move cwd, root_inode into a FileSystem structure
|
||||
// TODO: should cwd be a String or INode?
|
||||
cwd: String,
|
||||
|
@ -14,6 +14,7 @@ lazy_static! {
|
||||
tgid: 0,
|
||||
host_tid: 0,
|
||||
exit_status: 0,
|
||||
is_detached: false,
|
||||
cwd: "/".to_owned(),
|
||||
elf_path: "/".to_owned(),
|
||||
clear_child_tid: None,
|
||||
@ -28,6 +29,7 @@ lazy_static! {
|
||||
}
|
||||
|
||||
impl Process {
|
||||
// TODO: this constructor has become complicated enough to justify using builders
|
||||
pub fn new(
|
||||
cwd: &str,
|
||||
elf_path: &str,
|
||||
@ -35,6 +37,7 @@ impl Process {
|
||||
vm_ref: ProcessVMRef,
|
||||
file_table_ref: FileTableRef,
|
||||
rlimits_ref: ResourceLimitsRef,
|
||||
is_detached: bool,
|
||||
) -> Result<(pid_t, ProcessRef)> {
|
||||
let new_pid = process_table::alloc_pid();
|
||||
let new_process_ref = Arc::new(SgxMutex::new(Process {
|
||||
@ -48,6 +51,7 @@ impl Process {
|
||||
elf_path: elf_path.to_owned(),
|
||||
clear_child_tid: None,
|
||||
exit_status: 0,
|
||||
is_detached: is_detached,
|
||||
parent: None,
|
||||
children: Vec::new(),
|
||||
waiting_children: None,
|
||||
|
@ -111,7 +111,7 @@ fn new_process(
|
||||
Arc::new(SgxMutex::new(files))
|
||||
};
|
||||
let rlimits_ref = Default::default();
|
||||
Process::new(&cwd, elf_path, task, vm_ref, files_ref, rlimits_ref)?
|
||||
Process::new(&cwd, elf_path, task, vm_ref, files_ref, rlimits_ref, false)?
|
||||
};
|
||||
parent_adopts_new_child(&parent_ref, &new_process_ref);
|
||||
process_table::put(new_pid, new_process_ref.clone());
|
||||
|
@ -79,7 +79,7 @@ pub fn do_clone(
|
||||
let rlimits_ref = current.get_rlimits().clone();
|
||||
let elf_path = ¤t.elf_path;
|
||||
let cwd = ¤t.cwd;
|
||||
Process::new(cwd, elf_path, task, vm_ref, files_ref, rlimits_ref)?
|
||||
Process::new(cwd, elf_path, task, vm_ref, files_ref, rlimits_ref, true)?
|
||||
};
|
||||
|
||||
if let Some(ctid) = ctid {
|
||||
|
Loading…
Reference in New Issue
Block a user