Skip to content

Commit 49da0ac

Browse files
committed
Avoid fork/exec spawning on tvOS/watchOS, as those functions are marked as prohibited
1 parent b80e0b7 commit 49da0ac

File tree

1 file changed

+48
-4
lines changed

1 file changed

+48
-4
lines changed

library/std/src/sys/unix/process/process_unix.rs

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ use crate::sys::weak::raw_syscall;
1515

1616
#[cfg(any(
1717
target_os = "macos",
18+
target_os = "watchos",
19+
target_os = "tvos",
1820
target_os = "freebsd",
1921
all(target_os = "linux", target_env = "gnu"),
2022
all(target_os = "linux", target_env = "musl"),
@@ -28,7 +30,12 @@ use libc::RTP_ID as pid_t;
2830
#[cfg(not(target_os = "vxworks"))]
2931
use libc::{c_int, pid_t};
3032

31-
#[cfg(not(any(target_os = "vxworks", target_os = "l4re")))]
33+
#[cfg(not(any(
34+
target_os = "vxworks",
35+
target_os = "l4re",
36+
target_os = "tvos",
37+
target_os = "watchos",
38+
)))]
3239
use libc::{gid_t, uid_t};
3340

3441
cfg_if::cfg_if! {
@@ -84,7 +91,6 @@ impl Command {
8491
if let Some(ret) = self.posix_spawn(&theirs, envp.as_ref())? {
8592
return Ok((ret, ours));
8693
}
87-
8894
let (input, output) = sys::pipe::anon_pipe()?;
8995

9096
// Whatever happens after the fork is almost for sure going to touch or
@@ -166,9 +172,32 @@ impl Command {
166172
crate::sys_common::process::wait_with_output(proc, pipes)
167173
}
168174

175+
// WatchOS and TVOS can theoretically spawn processes using `posix_spawn*`
176+
// (although it just fails with a runtime error AFAICT, so we don't yet
177+
// support it in `std`), but forbid use of `fork`/`exec*`. It's unclear the
178+
// extent to which these is restricted, but the headers say
179+
// `__WATCHOS_PROHIBITED __TVOS_PROHIBITED`, so we go out of our way to
180+
// avoid containing any calls to them at all, to avoid linking against their
181+
// symbols on those targets.
182+
#[cfg(any(target_os = "tvos", target_os = "watchos"))]
183+
const ERR_APPLE_TV_WATCH_NO_FORK_EXEC: Error = io::const_io_error!(
184+
ErrorKind::Unsupported,
185+
"`fork`+`exec`-based process spawning is not supported on this target",
186+
);
187+
188+
#[cfg(any(target_os = "tvos", target_os = "watchos"))]
189+
unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
190+
return Err(Self::ERR_APPLE_TV_WATCH_NO_FORK_EXEC);
191+
}
192+
169193
// Attempts to fork the process. If successful, returns Ok((0, -1))
170194
// in the child, and Ok((child_pid, -1)) in the parent.
171-
#[cfg(not(any(target_os = "linux", all(target_os = "nto", target_env = "nto71"))))]
195+
#[cfg(not(any(
196+
target_os = "linux",
197+
target_os = "watchos",
198+
target_os = "tvos",
199+
all(target_os = "nto", target_env = "nto71"),
200+
)))]
172201
unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
173202
cvt(libc::fork()).map(|res| (res, -1))
174203
}
@@ -339,6 +368,7 @@ impl Command {
339368
// allocation). Instead we just close it manually. This will never
340369
// have the drop glue anyway because this code never returns (the
341370
// child will either exec() or invoke libc::exit)
371+
#[cfg(not(any(target_os = "tvos", target_os = "watchos")))]
342372
unsafe fn do_exec(
343373
&mut self,
344374
stdio: ChildPipes,
@@ -445,8 +475,19 @@ impl Command {
445475
Err(io::Error::last_os_error())
446476
}
447477

478+
#[cfg(any(target_os = "tvos", target_os = "watchos"))]
479+
unsafe fn do_exec(
480+
&mut self,
481+
_stdio: ChildPipes,
482+
_maybe_envp: Option<&CStringArray>,
483+
) -> Result<!, io::Error> {
484+
return Err(Self::ERR_APPLE_TV_WATCH_NO_FORK_EXEC);
485+
}
486+
448487
#[cfg(not(any(
449488
target_os = "macos",
489+
target_os = "tvos",
490+
target_os = "watchos",
450491
target_os = "freebsd",
451492
all(target_os = "linux", target_env = "gnu"),
452493
all(target_os = "linux", target_env = "musl"),
@@ -464,6 +505,9 @@ impl Command {
464505
// directly.
465506
#[cfg(any(
466507
target_os = "macos",
508+
// FIXME: `target_os = "ios"`?
509+
target_os = "tvos",
510+
target_os = "watchos",
467511
target_os = "freebsd",
468512
all(target_os = "linux", target_env = "gnu"),
469513
all(target_os = "linux", target_env = "musl"),
@@ -550,7 +594,7 @@ impl Command {
550594
}
551595
let addchdir = match self.get_cwd() {
552596
Some(cwd) => {
553-
if cfg!(target_os = "macos") {
597+
if cfg!(any(target_os = "macos", target_os = "tvos", target_os = "watchos")) {
554598
// There is a bug in macOS where a relative executable
555599
// path like "../myprogram" will cause `posix_spawn` to
556600
// successfully launch the program, but erroneously return

0 commit comments

Comments
 (0)