]> git.lizzy.rs Git - rust.git/commitdiff
Updated Fuchsia support for std::process. Adds support for try_wait. Misc. updates...
authorTheodore DeRego <tedsta@google.com>
Tue, 24 Jan 2017 21:01:47 +0000 (13:01 -0800)
committerTheodore DeRego <tedsta@google.com>
Tue, 24 Jan 2017 21:13:42 +0000 (13:13 -0800)
src/libstd/sys/unix/process/magenta.rs
src/libstd/sys/unix/process/process_fuchsia.rs

index 2bb005be4ec93421675a9ab2d5189e7bc0a8e1d0..a81bedcad22ff6034b3b0261ec5bb761a80d9722 100644 (file)
@@ -41,8 +41,6 @@
 
 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: T) -> io::Result<T> where T: TryInto<mx_status_t>+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 @@ pub fn mx_object_get_info(handle: mx_handle_t, topic: u32, buffer: *mut c_void,
                               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 @@ pub fn launchpad_arguments(lp: *mut launchpad_t, argc: c_int,
 
     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;
index f0a42b127998c241881d007bd40a7041bdab9c73..87acb0ed9b977e4fe1dc9c7da72e27e0e8d1b2d7 100644 (file)
@@ -54,7 +54,7 @@ unsafe fn do_exec(&mut self, stdio: ChildPipes)
                       -> 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 Drop for LaunchpadDestructor {
             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 Drop for LaunchpadDestructor {
 
         // 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 @@ pub fn wait(&mut self) -> io::Result<ExitStatus> {
         }
         Ok(ExitStatus::new(proc_info.rec.return_code))
     }
+
+    pub fn try_wait(&mut self) -> io::Result<ExitStatus> {
+        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::<mx_info_process_t>(), &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 {