Removed Option<ExitStatus> member from fuchsia Process struct. Destroy launchpads and close handles in Drop impls rather than manually

This commit is contained in:
Theodore DeRego
2016-11-30 14:20:44 -08:00
parent 5c1c48532f
commit 8d9d07a1ca
2 changed files with 45 additions and 32 deletions

View File

@@ -42,6 +42,30 @@ pub const MX_INFO_PROCESS : mx_object_info_topic_t = 3;
pub const MX_HND_TYPE_JOB: u32 = 6; pub const MX_HND_TYPE_JOB: u32 = 6;
// Safe wrapper around mx_handle_t
pub struct Handle {
raw: mx_handle_t,
}
impl Handle {
pub fn new(raw: mx_handle_t) -> Handle {
Handle {
raw: raw,
}
}
pub fn raw(&self) -> mx_handle_t {
self.raw
}
}
impl Drop for Handle {
fn drop(&mut self) {
use sys::mx_cvt;
unsafe { mx_cvt(mx_handle_close(self.raw)).expect("Failed to close mx_handle_t"); }
}
}
// Common MX_INFO header // Common MX_INFO header
#[derive(Default)] #[derive(Default)]
#[repr(C)] #[repr(C)]
@@ -68,6 +92,8 @@ pub struct mx_info_process_t {
} }
extern { extern {
pub fn mx_task_kill(handle: mx_handle_t) -> mx_status_t;
pub fn mx_handle_close(handle: mx_handle_t) -> mx_status_t; pub fn mx_handle_close(handle: mx_handle_t) -> mx_status_t;
pub fn mx_handle_duplicate(handle: mx_handle_t, rights: mx_rights_t, pub fn mx_handle_duplicate(handle: mx_handle_t, rights: mx_rights_t,

View File

@@ -14,7 +14,7 @@ use mem;
use ptr; use ptr;
use sys::mx_cvt; use sys::mx_cvt;
use sys::magenta::{launchpad_t, mx_handle_t}; use sys::magenta::{Handle, launchpad_t, mx_handle_t};
use sys::process::process_common::*; use sys::process::process_common::*;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -33,7 +33,7 @@ impl Command {
let (launchpad, process_handle) = unsafe { self.do_exec(theirs)? }; let (launchpad, process_handle) = unsafe { self.do_exec(theirs)? };
Ok((Process { launchpad: launchpad, handle: process_handle, status: None }, ours)) Ok((Process { launchpad: launchpad, handle: Handle::new(process_handle) }, ours))
} }
pub fn exec(&mut self, default: Stdio) -> io::Error { pub fn exec(&mut self, default: Stdio) -> io::Error {
@@ -116,7 +116,7 @@ impl Command {
let process_handle = mx_cvt(launchpad_start(launchpad))?; let process_handle = mx_cvt(launchpad_start(launchpad))?;
// Successfully started the launchpad, so launchpad_destroy shouldn't get called // Successfully started the launchpad
mem::forget(launchpad_destructor); mem::forget(launchpad_destructor);
Ok((launchpad, process_handle)) Ok((launchpad, process_handle))
@@ -129,62 +129,49 @@ impl Command {
pub struct Process { pub struct Process {
launchpad: *mut launchpad_t, launchpad: *mut launchpad_t,
handle: mx_handle_t, handle: Handle,
status: Option<ExitStatus>,
} }
impl Process { impl Process {
pub fn id(&self) -> u32 { pub fn id(&self) -> u32 {
self.handle as u32 self.handle.raw() as u32
} }
pub fn kill(&mut self) -> io::Result<()> { pub fn kill(&mut self) -> io::Result<()> {
use sys::magenta::*; use sys::magenta::*;
// If we've already waited on this process then the pid can be recycled unsafe { mx_cvt(mx_task_kill(self.handle.raw()))?; }
// and used for another process, and we probably shouldn't be killing
// random processes, so just return an error.
if self.status.is_some() {
Err(io::Error::new(io::ErrorKind::InvalidInput,
"invalid argument: can't kill an exited process"))
} else {
unsafe {
mx_cvt(mx_handle_close(self.handle))?;
launchpad_destroy(self.launchpad);
}
Ok(()) Ok(())
} }
}
pub fn wait(&mut self) -> io::Result<ExitStatus> { pub fn wait(&mut self) -> io::Result<ExitStatus> {
use default::Default; use default::Default;
use sys::magenta::*; use sys::magenta::*;
if let Some(status) = self.status {
return Ok(status)
}
let mut proc_info: mx_info_process_t = Default::default(); let mut proc_info: mx_info_process_t = Default::default();
let mut actual: mx_size_t = 0; let mut actual: mx_size_t = 0;
let mut avail: mx_size_t = 0; let mut avail: mx_size_t = 0;
unsafe { unsafe {
mx_cvt(mx_handle_wait_one(self.handle, MX_TASK_TERMINATED, mx_cvt(mx_handle_wait_one(self.handle.raw(), MX_TASK_TERMINATED,
MX_TIME_INFINITE, ptr::null_mut()))?; MX_TIME_INFINITE, ptr::null_mut()))?;
mx_cvt(mx_object_get_info(self.handle, MX_INFO_PROCESS, mx_cvt(mx_object_get_info(self.handle.raw(), MX_INFO_PROCESS,
&mut proc_info as *mut _ as *mut libc::c_void, &mut proc_info as *mut _ as *mut libc::c_void,
mem::size_of::<mx_info_process_t>(), &mut actual, mem::size_of::<mx_info_process_t>(), &mut actual,
&mut avail))?; &mut avail))?;
} }
if actual != 1 { if actual != 1 {
return Err(io::Error::new(io::ErrorKind::InvalidInput, return Err(io::Error::new(io::ErrorKind::InvalidData,
"Failed to get exit status of process")); "Failed to get exit status of process"));
} }
self.status = Some(ExitStatus::new(proc_info.rec.return_code));
unsafe {
mx_cvt(mx_handle_close(self.handle))?;
launchpad_destroy(self.launchpad);
}
Ok(ExitStatus::new(proc_info.rec.return_code)) Ok(ExitStatus::new(proc_info.rec.return_code))
} }
} }
impl Drop for Process {
fn drop(&mut self) {
use sys::magenta::launchpad_destroy;
unsafe { launchpad_destroy(self.launchpad); }
}
}