Skip to content

Commit 185d908

Browse files
committed
Auto merge of #39277 - tedsta:fuchsia_std_process, r=alexcrichton
Update Fuchsia support for std::process. - Adds support for try_wait. - Miscellaneous updates to keep up with Magenta changes. I'll begin `sys/fuchsia` soon, just been bogged down with my actual job lately (I'm not on the Fuchsia team).
2 parents c0d0e68 + bbe419f commit 185d908

File tree

2 files changed

+167
-23
lines changed

2 files changed

+167
-23
lines changed

src/libstd/sys/unix/process/magenta.rs

+127-13
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ pub type mx_object_info_topic_t = u32;
4141

4242
pub const MX_INFO_PROCESS : mx_object_info_topic_t = 3;
4343

44-
pub const MX_HND_TYPE_JOB: u32 = 6;
45-
4644
pub fn mx_cvt<T>(t: T) -> io::Result<T> where T: TryInto<mx_status_t>+Copy {
4745
if let Ok(status) = TryInto::try_into(t) {
4846
if status < 0 {
@@ -104,6 +102,8 @@ pub struct mx_info_process_t {
104102
}
105103

106104
extern {
105+
static __magenta_job_default: mx_handle_t;
106+
107107
pub fn mx_task_kill(handle: mx_handle_t) -> mx_status_t;
108108

109109
pub fn mx_handle_close(handle: mx_handle_t) -> mx_status_t;
@@ -119,21 +119,14 @@ extern {
119119
avail: *mut mx_size_t) -> mx_status_t;
120120
}
121121

122-
// Handle Info entries associate a type and optional
123-
// argument with each handle included in the process
124-
// arguments message.
125-
pub fn mx_hnd_info(hnd_type: u32, arg: u32) -> u32 {
126-
(hnd_type & 0xFFFF) | ((arg & 0xFFFF) << 16)
127-
}
128-
129-
extern {
130-
pub fn mxio_get_startup_handle(id: u32) -> mx_handle_t;
122+
pub fn mx_job_default() -> mx_handle_t {
123+
unsafe { return __magenta_job_default; }
131124
}
132125

133126
// From `enum special_handles` in system/ulib/launchpad/launchpad.c
134-
#[allow(unused)] pub const HND_LOADER_SVC: usize = 0;
127+
// HND_LOADER_SVC = 0
135128
// HND_EXEC_VMO = 1
136-
#[allow(unused)] pub const HND_SPECIAL_COUNT: usize = 2;
129+
pub const HND_SPECIAL_COUNT: usize = 2;
137130

138131
#[repr(C)]
139132
pub struct launchpad_t {
@@ -188,3 +181,124 @@ extern {
188181

189182
pub fn launchpad_vmo_from_file(filename: *const c_char) -> mx_handle_t;
190183
}
184+
185+
// Errors
186+
187+
#[allow(unused)] pub const ERR_INTERNAL: mx_status_t = -1;
188+
189+
// ERR_NOT_SUPPORTED: The operation is not implemented, supported,
190+
// or enabled.
191+
#[allow(unused)] pub const ERR_NOT_SUPPORTED: mx_status_t = -2;
192+
193+
// ERR_NO_RESOURCES: The system was not able to allocate some resource
194+
// needed for the operation.
195+
#[allow(unused)] pub const ERR_NO_RESOURCES: mx_status_t = -5;
196+
197+
// ERR_NO_MEMORY: The system was not able to allocate memory needed
198+
// for the operation.
199+
#[allow(unused)] pub const ERR_NO_MEMORY: mx_status_t = -4;
200+
201+
// ERR_CALL_FAILED: The second phase of mx_channel_call(; did not complete
202+
// successfully.
203+
#[allow(unused)] pub const ERR_CALL_FAILED: mx_status_t = -53;
204+
205+
// ======= Parameter errors =======
206+
// ERR_INVALID_ARGS: an argument is invalid, ex. null pointer
207+
#[allow(unused)] pub const ERR_INVALID_ARGS: mx_status_t = -10;
208+
209+
// ERR_WRONG_TYPE: The subject of the operation is the wrong type to
210+
// perform the operation.
211+
// Example: Attempting a message_read on a thread handle.
212+
#[allow(unused)] pub const ERR_WRONG_TYPE: mx_status_t = -54;
213+
214+
// ERR_BAD_SYSCALL: The specified syscall number is invalid.
215+
#[allow(unused)] pub const ERR_BAD_SYSCALL: mx_status_t = -11;
216+
217+
// ERR_BAD_HANDLE: A specified handle value does not refer to a handle.
218+
#[allow(unused)] pub const ERR_BAD_HANDLE: mx_status_t = -12;
219+
220+
// ERR_OUT_OF_RANGE: An argument is outside the valid range for this
221+
// operation.
222+
#[allow(unused)] pub const ERR_OUT_OF_RANGE: mx_status_t = -13;
223+
224+
// ERR_BUFFER_TOO_SMALL: A caller provided buffer is too small for
225+
// this operation.
226+
#[allow(unused)] pub const ERR_BUFFER_TOO_SMALL: mx_status_t = -14;
227+
228+
// ======= Precondition or state errors =======
229+
// ERR_BAD_STATE: operation failed because the current state of the
230+
// object does not allow it, or a precondition of the operation is
231+
// not satisfied
232+
#[allow(unused)] pub const ERR_BAD_STATE: mx_status_t = -20;
233+
234+
// ERR_NOT_FOUND: The requested entity is not found.
235+
#[allow(unused)] pub const ERR_NOT_FOUND: mx_status_t = -3;
236+
237+
// ERR_ALREADY_EXISTS: An object with the specified identifier
238+
// already exists.
239+
// Example: Attempting to create a file when a file already exists
240+
// with that name.
241+
#[allow(unused)] pub const ERR_ALREADY_EXISTS: mx_status_t = -15;
242+
243+
// ERR_ALREADY_BOUND: The operation failed because the named entity
244+
// is already owned or controlled by another entity. The operation
245+
// could succeed later if the current owner releases the entity.
246+
#[allow(unused)] pub const ERR_ALREADY_BOUND: mx_status_t = -16;
247+
248+
// ERR_TIMED_OUT: The time limit for the operation elapsed before
249+
// the operation completed.
250+
#[allow(unused)] pub const ERR_TIMED_OUT: mx_status_t = -23;
251+
252+
// ERR_HANDLE_CLOSED: a handle being waited on was closed
253+
#[allow(unused)] pub const ERR_HANDLE_CLOSED: mx_status_t = -24;
254+
255+
// ERR_REMOTE_CLOSED: The operation failed because the remote end
256+
// of the subject of the operation was closed.
257+
#[allow(unused)] pub const ERR_REMOTE_CLOSED: mx_status_t = -25;
258+
259+
// ERR_UNAVAILABLE: The subject of the operation is currently unable
260+
// to perform the operation.
261+
// Note: This is used when there's no direct way for the caller to
262+
// observe when the subject will be able to perform the operation
263+
// and should thus retry.
264+
#[allow(unused)] pub const ERR_UNAVAILABLE: mx_status_t = -26;
265+
266+
// ERR_SHOULD_WAIT: The operation cannot be performed currently but
267+
// potentially could succeed if the caller waits for a prerequisite
268+
// to be satisfied, for example waiting for a handle to be readable
269+
// or writable.
270+
// Example: Attempting to read from a message pipe that has no
271+
// messages waiting but has an open remote will return ERR_SHOULD_WAIT.
272+
// Attempting to read from a message pipe that has no messages waiting
273+
// and has a closed remote end will return ERR_REMOTE_CLOSED.
274+
#[allow(unused)] pub const ERR_SHOULD_WAIT: mx_status_t = -27;
275+
276+
// ======= Permission check errors =======
277+
// ERR_ACCESS_DENIED: The caller did not have permission to perform
278+
// the specified operation.
279+
#[allow(unused)] pub const ERR_ACCESS_DENIED: mx_status_t = -30;
280+
281+
// ======= Input-output errors =======
282+
// ERR_IO: Otherwise unspecified error occurred during I/O.
283+
#[allow(unused)] pub const ERR_IO: mx_status_t = -40;
284+
285+
// ERR_REFUSED: The entity the I/O operation is being performed on
286+
// rejected the operation.
287+
// Example: an I2C device NAK'ing a transaction or a disk controller
288+
// rejecting an invalid command.
289+
#[allow(unused)] pub const ERR_IO_REFUSED: mx_status_t = -41;
290+
291+
// ERR_IO_DATA_INTEGRITY: The data in the operation failed an integrity
292+
// check and is possibly corrupted.
293+
// Example: CRC or Parity error.
294+
#[allow(unused)] pub const ERR_IO_DATA_INTEGRITY: mx_status_t = -42;
295+
296+
// ERR_IO_DATA_LOSS: The data in the operation is currently unavailable
297+
// and may be permanently lost.
298+
// Example: A disk block is irrecoverably damaged.
299+
#[allow(unused)] pub const ERR_IO_DATA_LOSS: mx_status_t = -43;
300+
301+
// Filesystem specific errors
302+
#[allow(unused)] pub const ERR_BAD_PATH: mx_status_t = -50;
303+
#[allow(unused)] pub const ERR_NOT_DIR: mx_status_t = -51;
304+
#[allow(unused)] pub const ERR_NOT_FILE: mx_status_t = -52;

src/libstd/sys/unix/process/process_fuchsia.rs

+40-10
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ impl Command {
5454
-> io::Result<(*mut launchpad_t, mx_handle_t)> {
5555
use sys::process::magenta::*;
5656

57-
let job_handle = mxio_get_startup_handle(mx_hnd_info(MX_HND_TYPE_JOB, 0));
57+
let job_handle = mx_job_default();
5858
let envp = match *self.get_envp() {
5959
Some(ref envp) => envp.as_ptr(),
6060
None => ptr::null(),
@@ -66,14 +66,14 @@ impl Command {
6666
fn drop(&mut self) { unsafe { launchpad_destroy(self.0); } }
6767
}
6868

69-
let mut launchpad: *mut launchpad_t = ptr::null_mut();
70-
let launchpad_destructor = LaunchpadDestructor(launchpad);
71-
7269
// Duplicate the job handle
7370
let mut job_copy: mx_handle_t = MX_HANDLE_INVALID;
7471
mx_cvt(mx_handle_duplicate(job_handle, MX_RIGHT_SAME_RIGHTS, &mut job_copy))?;
7572
// Create a launchpad
73+
let mut launchpad: *mut launchpad_t = ptr::null_mut();
7674
mx_cvt(launchpad_create(job_copy, self.get_argv()[0], &mut launchpad))?;
75+
let launchpad_destructor = LaunchpadDestructor(launchpad);
76+
7777
// Set the process argv
7878
mx_cvt(launchpad_arguments(launchpad, self.get_argv().len() as i32 - 1,
7979
self.get_argv().as_ptr()))?;
@@ -88,19 +88,19 @@ impl Command {
8888

8989
// Clone stdin, stdout, and stderr
9090
if let Some(fd) = stdio.stdin.fd() {
91-
launchpad_transfer_fd(launchpad, fd, 0);
91+
mx_cvt(launchpad_transfer_fd(launchpad, fd, 0))?;
9292
} else {
93-
launchpad_clone_fd(launchpad, 0, 0);
93+
mx_cvt(launchpad_clone_fd(launchpad, 0, 0))?;
9494
}
9595
if let Some(fd) = stdio.stdout.fd() {
96-
launchpad_transfer_fd(launchpad, fd, 1);
96+
mx_cvt(launchpad_transfer_fd(launchpad, fd, 1))?;
9797
} else {
98-
launchpad_clone_fd(launchpad, 1, 1);
98+
mx_cvt(launchpad_clone_fd(launchpad, 1, 1))?;
9999
}
100100
if let Some(fd) = stdio.stderr.fd() {
101-
launchpad_transfer_fd(launchpad, fd, 2);
101+
mx_cvt(launchpad_transfer_fd(launchpad, fd, 2))?;
102102
} else {
103-
launchpad_clone_fd(launchpad, 2, 2);
103+
mx_cvt(launchpad_clone_fd(launchpad, 2, 2))?;
104104
}
105105

106106
// We don't want FileDesc::drop to be called on any stdio. It would close their fds. The
@@ -164,6 +164,36 @@ impl Process {
164164
}
165165
Ok(ExitStatus::new(proc_info.rec.return_code))
166166
}
167+
168+
pub fn try_wait(&mut self) -> io::Result<ExitStatus> {
169+
use default::Default;
170+
use sys::process::magenta::*;
171+
172+
let mut proc_info: mx_info_process_t = Default::default();
173+
let mut actual: mx_size_t = 0;
174+
let mut avail: mx_size_t = 0;
175+
176+
unsafe {
177+
let status = mx_handle_wait_one(self.handle.raw(), MX_TASK_TERMINATED,
178+
0, ptr::null_mut());
179+
match status {
180+
0 => { }, // Success
181+
x if x == ERR_TIMED_OUT => {
182+
return Err(io::Error::from(io::ErrorKind::WouldBlock));
183+
},
184+
_ => { panic!("Failed to wait on process handle: {}", status); },
185+
}
186+
mx_cvt(mx_object_get_info(self.handle.raw(), MX_INFO_PROCESS,
187+
&mut proc_info as *mut _ as *mut libc::c_void,
188+
mem::size_of::<mx_info_process_t>(), &mut actual,
189+
&mut avail))?;
190+
}
191+
if actual != 1 {
192+
return Err(io::Error::new(io::ErrorKind::InvalidData,
193+
"Failed to get exit status of process"));
194+
}
195+
Ok(ExitStatus::new(proc_info.rec.return_code))
196+
}
167197
}
168198

169199
impl Drop for Process {

0 commit comments

Comments
 (0)