diff --git a/src/libstd/sys/unix/process/magenta.rs b/src/libstd/sys/unix/process/magenta.rs index 2bb005be4ec93..a81bedcad22ff 100644 --- a/src/libstd/sys/unix/process/magenta.rs +++ b/src/libstd/sys/unix/process/magenta.rs @@ -41,8 +41,6 @@ pub type mx_object_info_topic_t = u32; pub const MX_INFO_PROCESS : mx_object_info_topic_t = 3; -pub const MX_HND_TYPE_JOB: u32 = 6; - pub fn mx_cvt(t: T) -> io::Result where T: TryInto+Copy { if let Ok(status) = TryInto::try_into(t) { if status < 0 { @@ -104,6 +102,8 @@ pub struct mx_info_process_t { } extern { + static __magenta_job_default: mx_handle_t; + pub fn mx_task_kill(handle: mx_handle_t) -> mx_status_t; pub fn mx_handle_close(handle: mx_handle_t) -> mx_status_t; @@ -119,21 +119,14 @@ extern { avail: *mut mx_size_t) -> mx_status_t; } -// Handle Info entries associate a type and optional -// argument with each handle included in the process -// arguments message. -pub fn mx_hnd_info(hnd_type: u32, arg: u32) -> u32 { - (hnd_type & 0xFFFF) | ((arg & 0xFFFF) << 16) -} - -extern { - pub fn mxio_get_startup_handle(id: u32) -> mx_handle_t; +pub fn mx_job_default() -> mx_handle_t { + unsafe { return __magenta_job_default; } } // From `enum special_handles` in system/ulib/launchpad/launchpad.c -#[allow(unused)] pub const HND_LOADER_SVC: usize = 0; +// HND_LOADER_SVC = 0 // HND_EXEC_VMO = 1 -#[allow(unused)] pub const HND_SPECIAL_COUNT: usize = 2; +pub const HND_SPECIAL_COUNT: usize = 2; #[repr(C)] pub struct launchpad_t { @@ -188,3 +181,124 @@ extern { pub fn launchpad_vmo_from_file(filename: *const c_char) -> mx_handle_t; } + +// Errors + +#[allow(unused)] pub const ERR_INTERNAL: mx_status_t = -1; + +// ERR_NOT_SUPPORTED: The operation is not implemented, supported, +// or enabled. +#[allow(unused)] pub const ERR_NOT_SUPPORTED: mx_status_t = -2; + +// ERR_NO_RESOURCES: The system was not able to allocate some resource +// needed for the operation. +#[allow(unused)] pub const ERR_NO_RESOURCES: mx_status_t = -5; + +// ERR_NO_MEMORY: The system was not able to allocate memory needed +// for the operation. +#[allow(unused)] pub const ERR_NO_MEMORY: mx_status_t = -4; + +// ERR_CALL_FAILED: The second phase of mx_channel_call(; did not complete +// successfully. +#[allow(unused)] pub const ERR_CALL_FAILED: mx_status_t = -53; + +// ======= Parameter errors ======= +// ERR_INVALID_ARGS: an argument is invalid, ex. null pointer +#[allow(unused)] pub const ERR_INVALID_ARGS: mx_status_t = -10; + +// ERR_WRONG_TYPE: The subject of the operation is the wrong type to +// perform the operation. +// Example: Attempting a message_read on a thread handle. +#[allow(unused)] pub const ERR_WRONG_TYPE: mx_status_t = -54; + +// ERR_BAD_SYSCALL: The specified syscall number is invalid. +#[allow(unused)] pub const ERR_BAD_SYSCALL: mx_status_t = -11; + +// ERR_BAD_HANDLE: A specified handle value does not refer to a handle. +#[allow(unused)] pub const ERR_BAD_HANDLE: mx_status_t = -12; + +// ERR_OUT_OF_RANGE: An argument is outside the valid range for this +// operation. +#[allow(unused)] pub const ERR_OUT_OF_RANGE: mx_status_t = -13; + +// ERR_BUFFER_TOO_SMALL: A caller provided buffer is too small for +// this operation. +#[allow(unused)] pub const ERR_BUFFER_TOO_SMALL: mx_status_t = -14; + +// ======= Precondition or state errors ======= +// ERR_BAD_STATE: operation failed because the current state of the +// object does not allow it, or a precondition of the operation is +// not satisfied +#[allow(unused)] pub const ERR_BAD_STATE: mx_status_t = -20; + +// ERR_NOT_FOUND: The requested entity is not found. +#[allow(unused)] pub const ERR_NOT_FOUND: mx_status_t = -3; + +// ERR_ALREADY_EXISTS: An object with the specified identifier +// already exists. +// Example: Attempting to create a file when a file already exists +// with that name. +#[allow(unused)] pub const ERR_ALREADY_EXISTS: mx_status_t = -15; + +// ERR_ALREADY_BOUND: The operation failed because the named entity +// is already owned or controlled by another entity. The operation +// could succeed later if the current owner releases the entity. +#[allow(unused)] pub const ERR_ALREADY_BOUND: mx_status_t = -16; + +// ERR_TIMED_OUT: The time limit for the operation elapsed before +// the operation completed. +#[allow(unused)] pub const ERR_TIMED_OUT: mx_status_t = -23; + +// ERR_HANDLE_CLOSED: a handle being waited on was closed +#[allow(unused)] pub const ERR_HANDLE_CLOSED: mx_status_t = -24; + +// ERR_REMOTE_CLOSED: The operation failed because the remote end +// of the subject of the operation was closed. +#[allow(unused)] pub const ERR_REMOTE_CLOSED: mx_status_t = -25; + +// ERR_UNAVAILABLE: The subject of the operation is currently unable +// to perform the operation. +// Note: This is used when there's no direct way for the caller to +// observe when the subject will be able to perform the operation +// and should thus retry. +#[allow(unused)] pub const ERR_UNAVAILABLE: mx_status_t = -26; + +// ERR_SHOULD_WAIT: The operation cannot be performed currently but +// potentially could succeed if the caller waits for a prerequisite +// to be satisfied, for example waiting for a handle to be readable +// or writable. +// Example: Attempting to read from a message pipe that has no +// messages waiting but has an open remote will return ERR_SHOULD_WAIT. +// Attempting to read from a message pipe that has no messages waiting +// and has a closed remote end will return ERR_REMOTE_CLOSED. +#[allow(unused)] pub const ERR_SHOULD_WAIT: mx_status_t = -27; + +// ======= Permission check errors ======= +// ERR_ACCESS_DENIED: The caller did not have permission to perform +// the specified operation. +#[allow(unused)] pub const ERR_ACCESS_DENIED: mx_status_t = -30; + +// ======= Input-output errors ======= +// ERR_IO: Otherwise unspecified error occurred during I/O. +#[allow(unused)] pub const ERR_IO: mx_status_t = -40; + +// ERR_REFUSED: The entity the I/O operation is being performed on +// rejected the operation. +// Example: an I2C device NAK'ing a transaction or a disk controller +// rejecting an invalid command. +#[allow(unused)] pub const ERR_IO_REFUSED: mx_status_t = -41; + +// ERR_IO_DATA_INTEGRITY: The data in the operation failed an integrity +// check and is possibly corrupted. +// Example: CRC or Parity error. +#[allow(unused)] pub const ERR_IO_DATA_INTEGRITY: mx_status_t = -42; + +// ERR_IO_DATA_LOSS: The data in the operation is currently unavailable +// and may be permanently lost. +// Example: A disk block is irrecoverably damaged. +#[allow(unused)] pub const ERR_IO_DATA_LOSS: mx_status_t = -43; + +// Filesystem specific errors +#[allow(unused)] pub const ERR_BAD_PATH: mx_status_t = -50; +#[allow(unused)] pub const ERR_NOT_DIR: mx_status_t = -51; +#[allow(unused)] pub const ERR_NOT_FILE: mx_status_t = -52; diff --git a/src/libstd/sys/unix/process/process_fuchsia.rs b/src/libstd/sys/unix/process/process_fuchsia.rs index f0a42b127998c..87acb0ed9b977 100644 --- a/src/libstd/sys/unix/process/process_fuchsia.rs +++ b/src/libstd/sys/unix/process/process_fuchsia.rs @@ -54,7 +54,7 @@ impl Command { -> io::Result<(*mut launchpad_t, mx_handle_t)> { use sys::process::magenta::*; - let job_handle = mxio_get_startup_handle(mx_hnd_info(MX_HND_TYPE_JOB, 0)); + let job_handle = mx_job_default(); let envp = match *self.get_envp() { Some(ref envp) => envp.as_ptr(), None => ptr::null(), @@ -66,14 +66,14 @@ impl Command { fn drop(&mut self) { unsafe { launchpad_destroy(self.0); } } } - let mut launchpad: *mut launchpad_t = ptr::null_mut(); - let launchpad_destructor = LaunchpadDestructor(launchpad); - // Duplicate the job handle let mut job_copy: mx_handle_t = MX_HANDLE_INVALID; mx_cvt(mx_handle_duplicate(job_handle, MX_RIGHT_SAME_RIGHTS, &mut job_copy))?; // Create a launchpad + let mut launchpad: *mut launchpad_t = ptr::null_mut(); mx_cvt(launchpad_create(job_copy, self.get_argv()[0], &mut launchpad))?; + let launchpad_destructor = LaunchpadDestructor(launchpad); + // Set the process argv mx_cvt(launchpad_arguments(launchpad, self.get_argv().len() as i32 - 1, self.get_argv().as_ptr()))?; @@ -88,19 +88,19 @@ impl Command { // Clone stdin, stdout, and stderr if let Some(fd) = stdio.stdin.fd() { - launchpad_transfer_fd(launchpad, fd, 0); + mx_cvt(launchpad_transfer_fd(launchpad, fd, 0))?; } else { - launchpad_clone_fd(launchpad, 0, 0); + mx_cvt(launchpad_clone_fd(launchpad, 0, 0))?; } if let Some(fd) = stdio.stdout.fd() { - launchpad_transfer_fd(launchpad, fd, 1); + mx_cvt(launchpad_transfer_fd(launchpad, fd, 1))?; } else { - launchpad_clone_fd(launchpad, 1, 1); + mx_cvt(launchpad_clone_fd(launchpad, 1, 1))?; } if let Some(fd) = stdio.stderr.fd() { - launchpad_transfer_fd(launchpad, fd, 2); + mx_cvt(launchpad_transfer_fd(launchpad, fd, 2))?; } else { - launchpad_clone_fd(launchpad, 2, 2); + mx_cvt(launchpad_clone_fd(launchpad, 2, 2))?; } // We don't want FileDesc::drop to be called on any stdio. It would close their fds. The @@ -164,6 +164,36 @@ impl Process { } Ok(ExitStatus::new(proc_info.rec.return_code)) } + + pub fn try_wait(&mut self) -> io::Result { + use default::Default; + use sys::process::magenta::*; + + let mut proc_info: mx_info_process_t = Default::default(); + let mut actual: mx_size_t = 0; + let mut avail: mx_size_t = 0; + + unsafe { + let status = mx_handle_wait_one(self.handle.raw(), MX_TASK_TERMINATED, + 0, ptr::null_mut()); + match status { + 0 => { }, // Success + x if x == ERR_TIMED_OUT => { + return Err(io::Error::from(io::ErrorKind::WouldBlock)); + }, + _ => { panic!("Failed to wait on process handle: {}", status); }, + } + mx_cvt(mx_object_get_info(self.handle.raw(), MX_INFO_PROCESS, + &mut proc_info as *mut _ as *mut libc::c_void, + mem::size_of::(), &mut actual, + &mut avail))?; + } + if actual != 1 { + return Err(io::Error::new(io::ErrorKind::InvalidData, + "Failed to get exit status of process")); + } + Ok(ExitStatus::new(proc_info.rec.return_code)) + } } impl Drop for Process {