Avoid fork/exec spawning on tvOS/watchOS, as those functions are marked as prohibited
This commit is contained in:
parent
b80e0b7f53
commit
49da0acb71
1 changed files with 48 additions and 4 deletions
|
@ -15,6 +15,8 @@ use crate::sys::weak::raw_syscall;
|
||||||
|
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
target_os = "macos",
|
target_os = "macos",
|
||||||
|
target_os = "watchos",
|
||||||
|
target_os = "tvos",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
all(target_os = "linux", target_env = "gnu"),
|
all(target_os = "linux", target_env = "gnu"),
|
||||||
all(target_os = "linux", target_env = "musl"),
|
all(target_os = "linux", target_env = "musl"),
|
||||||
|
@ -28,7 +30,12 @@ use libc::RTP_ID as pid_t;
|
||||||
#[cfg(not(target_os = "vxworks"))]
|
#[cfg(not(target_os = "vxworks"))]
|
||||||
use libc::{c_int, pid_t};
|
use libc::{c_int, pid_t};
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "vxworks", target_os = "l4re")))]
|
#[cfg(not(any(
|
||||||
|
target_os = "vxworks",
|
||||||
|
target_os = "l4re",
|
||||||
|
target_os = "tvos",
|
||||||
|
target_os = "watchos",
|
||||||
|
)))]
|
||||||
use libc::{gid_t, uid_t};
|
use libc::{gid_t, uid_t};
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
|
@ -84,7 +91,6 @@ impl Command {
|
||||||
if let Some(ret) = self.posix_spawn(&theirs, envp.as_ref())? {
|
if let Some(ret) = self.posix_spawn(&theirs, envp.as_ref())? {
|
||||||
return Ok((ret, ours));
|
return Ok((ret, ours));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (input, output) = sys::pipe::anon_pipe()?;
|
let (input, output) = sys::pipe::anon_pipe()?;
|
||||||
|
|
||||||
// Whatever happens after the fork is almost for sure going to touch or
|
// Whatever happens after the fork is almost for sure going to touch or
|
||||||
|
@ -166,9 +172,32 @@ impl Command {
|
||||||
crate::sys_common::process::wait_with_output(proc, pipes)
|
crate::sys_common::process::wait_with_output(proc, pipes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WatchOS and TVOS can theoretically spawn processes using `posix_spawn*`
|
||||||
|
// (although it just fails with a runtime error AFAICT, so we don't yet
|
||||||
|
// support it in `std`), but forbid use of `fork`/`exec*`. It's unclear the
|
||||||
|
// extent to which these is restricted, but the headers say
|
||||||
|
// `__WATCHOS_PROHIBITED __TVOS_PROHIBITED`, so we go out of our way to
|
||||||
|
// avoid containing any calls to them at all, to avoid linking against their
|
||||||
|
// symbols on those targets.
|
||||||
|
#[cfg(any(target_os = "tvos", target_os = "watchos"))]
|
||||||
|
const ERR_APPLE_TV_WATCH_NO_FORK_EXEC: Error = io::const_io_error!(
|
||||||
|
ErrorKind::Unsupported,
|
||||||
|
"`fork`+`exec`-based process spawning is not supported on this target",
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "tvos", target_os = "watchos"))]
|
||||||
|
unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
|
||||||
|
return Err(Self::ERR_APPLE_TV_WATCH_NO_FORK_EXEC);
|
||||||
|
}
|
||||||
|
|
||||||
// Attempts to fork the process. If successful, returns Ok((0, -1))
|
// Attempts to fork the process. If successful, returns Ok((0, -1))
|
||||||
// in the child, and Ok((child_pid, -1)) in the parent.
|
// in the child, and Ok((child_pid, -1)) in the parent.
|
||||||
#[cfg(not(any(target_os = "linux", all(target_os = "nto", target_env = "nto71"))))]
|
#[cfg(not(any(
|
||||||
|
target_os = "linux",
|
||||||
|
target_os = "watchos",
|
||||||
|
target_os = "tvos",
|
||||||
|
all(target_os = "nto", target_env = "nto71"),
|
||||||
|
)))]
|
||||||
unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
|
unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
|
||||||
cvt(libc::fork()).map(|res| (res, -1))
|
cvt(libc::fork()).map(|res| (res, -1))
|
||||||
}
|
}
|
||||||
|
@ -339,6 +368,7 @@ impl Command {
|
||||||
// allocation). Instead we just close it manually. This will never
|
// allocation). Instead we just close it manually. This will never
|
||||||
// have the drop glue anyway because this code never returns (the
|
// have the drop glue anyway because this code never returns (the
|
||||||
// child will either exec() or invoke libc::exit)
|
// child will either exec() or invoke libc::exit)
|
||||||
|
#[cfg(not(any(target_os = "tvos", target_os = "watchos")))]
|
||||||
unsafe fn do_exec(
|
unsafe fn do_exec(
|
||||||
&mut self,
|
&mut self,
|
||||||
stdio: ChildPipes,
|
stdio: ChildPipes,
|
||||||
|
@ -445,8 +475,19 @@ impl Command {
|
||||||
Err(io::Error::last_os_error())
|
Err(io::Error::last_os_error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "tvos", target_os = "watchos"))]
|
||||||
|
unsafe fn do_exec(
|
||||||
|
&mut self,
|
||||||
|
_stdio: ChildPipes,
|
||||||
|
_maybe_envp: Option<&CStringArray>,
|
||||||
|
) -> Result<!, io::Error> {
|
||||||
|
return Err(Self::ERR_APPLE_TV_WATCH_NO_FORK_EXEC);
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(any(
|
#[cfg(not(any(
|
||||||
target_os = "macos",
|
target_os = "macos",
|
||||||
|
target_os = "tvos",
|
||||||
|
target_os = "watchos",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
all(target_os = "linux", target_env = "gnu"),
|
all(target_os = "linux", target_env = "gnu"),
|
||||||
all(target_os = "linux", target_env = "musl"),
|
all(target_os = "linux", target_env = "musl"),
|
||||||
|
@ -464,6 +505,9 @@ impl Command {
|
||||||
// directly.
|
// directly.
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
target_os = "macos",
|
target_os = "macos",
|
||||||
|
// FIXME: `target_os = "ios"`?
|
||||||
|
target_os = "tvos",
|
||||||
|
target_os = "watchos",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
all(target_os = "linux", target_env = "gnu"),
|
all(target_os = "linux", target_env = "gnu"),
|
||||||
all(target_os = "linux", target_env = "musl"),
|
all(target_os = "linux", target_env = "musl"),
|
||||||
|
@ -550,7 +594,7 @@ impl Command {
|
||||||
}
|
}
|
||||||
let addchdir = match self.get_cwd() {
|
let addchdir = match self.get_cwd() {
|
||||||
Some(cwd) => {
|
Some(cwd) => {
|
||||||
if cfg!(target_os = "macos") {
|
if cfg!(any(target_os = "macos", target_os = "tvos", target_os = "watchos")) {
|
||||||
// There is a bug in macOS where a relative executable
|
// There is a bug in macOS where a relative executable
|
||||||
// path like "../myprogram" will cause `posix_spawn` to
|
// path like "../myprogram" will cause `posix_spawn` to
|
||||||
// successfully launch the program, but erroneously return
|
// successfully launch the program, but erroneously return
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue