Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions library/std/src/os/unix/net/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,15 @@ pub(super) fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::s
let mut len = SUN_PATH_OFFSET + bytes.len();
match bytes.get(0) {
Some(&0) | None => {}
Some(_) => len += 1,
Some(_) => {
// on QNX7.1 and QNX8 the `len` value returned by the SUN_LEN
// macro in its libc does not include the null byte in the count so
// don't add it here to match what a C program passes to bind(2) and
// similar functions
if cfg!(not(any(target_os = "qnx", target_env = "nto71"))) {
len += 1
}
}
}
Ok((addr, len as libc::socklen_t))
}
Expand Down Expand Up @@ -247,7 +255,13 @@ impl SocketAddr {
} else if self.addr.sun_path[0] == 0 {
AddressKind::Abstract(ByteStr::from_bytes(&path[1..len]))
} else {
AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref())
// the value returned by getsockname(2) and similar on QNX7.1 and
// QNX8 does not count the NUL byte terminator of the path string,
// which matches the behavior of the SUN_LEN macro in libc, but
// other OSes do count the NUL byte so adjust accordingly
let end =
if cfg!(any(target_os = "qnx", target_env = "nto71")) { len } else { len - 1 };
AddressKind::Pathname(OsStr::from_bytes(&path[..end]).as_ref())
}
}
}
Expand Down
1 change: 1 addition & 0 deletions library/std/src/os/unix/net/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ impl UnixStream {
target_os = "netbsd",
target_os = "openbsd",
target_os = "nto",
target_os = "qnx",
target_vendor = "apple",
target_os = "cygwin"
))]
Expand Down
10 changes: 10 additions & 0 deletions library/std/src/os/unix/net/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::os::cygwin::net::{SocketAddrExt, UnixSocketExt};
use crate::os::linux::net::{SocketAddrExt, UnixSocketExt};
#[cfg(any(target_os = "android", target_os = "linux"))]
use crate::os::unix::io::AsRawFd;
use crate::path::Path;
use crate::test_helpers::tmpdir;
use crate::thread;
use crate::time::Duration;
Expand All @@ -22,6 +23,12 @@ macro_rules! or_panic {
};
}

#[test]
fn sock_addr_from_pathname() {
let address = or_panic!(SocketAddr::from_pathname("/path/to/socket"));
assert_eq!(address.as_pathname(), Some(Path::new("/path/to/socket")));
}

#[test]
#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
#[cfg_attr(target_os = "vxworks", ignore = "Unix sockets are not implemented in VxWorks")]
Expand All @@ -32,6 +39,7 @@ fn basic() {
let msg2 = b"world!";

let listener = or_panic!(UnixListener::bind(&socket_path));
assert_eq!(Some(&*socket_path), listener.local_addr().unwrap().as_pathname());
let thread = thread::spawn(move || {
let mut stream = or_panic!(listener.accept()).0;
let mut buf = [0; 5];
Expand Down Expand Up @@ -79,6 +87,8 @@ fn pair() {
let msg2 = b"world!";

let (mut s1, mut s2) = or_panic!(UnixStream::pair());
assert!(s1.local_addr().unwrap().is_unnamed());
assert!(s2.peer_addr().unwrap().is_unnamed());
let thread = thread::spawn(move || {
// s1 must be moved in or the test will hang!
let mut buf = [0; 5];
Expand Down
4 changes: 2 additions & 2 deletions library/std/src/os/unix/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ cfg_select! {
type GroupId = u16;
}
any(target_os = "nto", target_os = "qnx") => {
// Both IDs are signed, see `sys/target_nto.h` of the QNX Neutrino SDP.
// Both IDs are signed, see `sys/target_nto.h` of the QNX SDP.
// Only positive values should be used, see e.g.
// https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/s/setuid.html
// https://www.qnx.com/developers/docs/7.1/com.qnx.doc.neutrino.lib_ref/topic/s/setuid.html
type UserId = i32;
type GroupId = i32;
}
Expand Down
4 changes: 2 additions & 2 deletions library/std/src/sys/pal/unix/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,9 @@ impl Timespec {
})
}

// On QNX Neutrino, the maximum timespec for e.g. pthread_cond_timedwait
// On QNX, the maximum timespec for e.g. pthread_cond_timedwait
// is 2^64 nanoseconds
#[cfg(target_os = "nto")]
#[cfg(any(target_os = "nto", target_os = "qnx"))]
pub(in crate::sys) fn to_timespec_capped(&self) -> Option<libc::timespec> {
// Check if timeout in nanoseconds would fit into an u64
if (self.tv_nsec.as_inner() as u64)
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/paths/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
#[cfg(any(target_os = "nto", target_os = "qnx"))]
pub fn current_exe() -> io::Result<PathBuf> {
let mut e = crate::fs::read("/proc/self/exefile")?;
// Current versions of QNX Neutrino provide a null-terminated path.
// Current versions of QNX SDP provide a null-terminated path.
// Ensure the trailing null byte is not returned here.
if let Some(0) = e.last() {
e.pop();
Expand Down
43 changes: 39 additions & 4 deletions library/std/src/sys/process/unix/common/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,13 @@ fn test_process_group_posix_spawn() {
cmd.stdout(Stdio::MakePipe);
let (mut cat, _pipes) = t!(cmd.spawn(Stdio::Null, true));

let pid = cat.id() as libc::pid_t;
let pgid = libc::getpgid(pid);
assert_ne!(-1, pgid, "getpgid failed");
assert_eq!(pid, pgid, "child process ID does not match its process group ID");

// Check that we can kill its process group, which means there *is* one.
t!(cvt(libc::kill(-(cat.id() as libc::pid_t), libc::SIGINT)));
t!(cvt(libc::kill(-pgid, libc::SIGINT)));

t!(cat.wait());
}
Expand All @@ -127,8 +132,18 @@ fn test_process_group_no_posix_spawn() {
cmd.stdout(Stdio::MakePipe);
let (mut cat, _pipes) = t!(cmd.spawn(Stdio::Null, true));

let pid = cat.id() as libc::pid_t;
let pgid = libc::getpgid(pid);
assert_ne!(-1, pgid, "getpgid failed");
assert_eq!(pid, pgid, "child process ID does not match its process group ID");

if cfg!(target_os = "qnx") {
// kill(-pgid) appears to be unable to terminate the child process on QNX8
Comment thread
aapoalas marked this conversation as resolved.
return;
}

// Check that we can kill its process group, which means there *is* one.
t!(cvt(libc::kill(-(cat.id() as libc::pid_t), libc::SIGINT)));
t!(cvt(libc::kill(-pgid, libc::SIGINT)));

t!(cat.wait());
}
Expand All @@ -154,9 +169,19 @@ fn test_setsid_posix_spawn() {
let (mut cat, _pipes) = t!(cmd.spawn(Stdio::Null, true));

unsafe {
let pid = cat.id() as libc::pid_t;
let pgid = libc::getpgid(pid);
assert_ne!(-1, pgid, "getpgid failed");
assert_eq!(pid, pgid, "child process ID does not match its process group ID");

if cfg!(target_os = "qnx") {
// kill(-pgid) appears to be unable to terminate the child process on QNX8
return;
}

// Setsid will create a new session and process group, so check that
// we can kill the process group, which means there *is* one.
t!(cvt(libc::kill(-(cat.id() as libc::pid_t), libc::SIGINT)));
t!(cvt(libc::kill(-pgid, libc::SIGINT)));

t!(cat.wait());
}
Expand Down Expand Up @@ -184,9 +209,19 @@ fn test_setsid_no_posix_spawn() {
cmd.pre_exec(Box::new(|| Ok(()))); // pre_exec forces fork + exec rather than posix spawn.
let (mut cat, _pipes) = t!(cmd.spawn(Stdio::Null, true));

let pid = cat.id() as libc::pid_t;
let pgid = libc::getpgid(pid);
assert_ne!(-1, pgid, "getpgid failed");
assert_eq!(pid, pgid, "child process ID does not match its process group ID");

if cfg!(target_os = "qnx") {
// kill(-pgid) appears to be unable to terminate the child process on QNX8
return;
}

// Setsid will create a new session and process group, so check that
// we can kill the process group, which means there *is* one.
t!(cvt(libc::kill(-(cat.id() as libc::pid_t), libc::SIGINT)));
t!(cvt(libc::kill(-pgid, libc::SIGINT)));

t!(cat.wait());
}
Expand Down
10 changes: 5 additions & 5 deletions library/std/src/sys/process/unix/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,10 @@ impl Command {
cvt(libc::fork())
}

// On QNX Neutrino, fork can fail with EBADF in case "another thread might have opened
// On QNX SDP, fork can fail with EBADF in case "another thread might have opened
// or closed a file descriptor while the fork() was occurring".
// Documentation says "... or try calling fork() again". This is what we do here.
// See also https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html
// See also https://www.qnx.com/developers/docs/7.1/com.qnx.doc.neutrino.lib_ref/topic/f/fork.html
#[cfg(any(target_os = "nto", target_os = "qnx"))]
unsafe fn do_fork(&mut self) -> Result<pid_t, io::Error> {
use crate::sys::io::errno;
Expand Down Expand Up @@ -553,10 +553,10 @@ impl Command {
}
}

// On QNX Neutrino, posix_spawnp can fail with EBADF in case "another thread might have opened
// On QNX SDP, posix_spawnp can fail with EBADF in case "another thread might have opened
// or closed a file descriptor while the posix_spawn() was occurring".
// Documentation says "... or try calling posix_spawn() again". This is what we do here.
// See also http://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/p/posix_spawn.html
// See also https://www.qnx.com/developers/docs/7.1/com.qnx.doc.neutrino.lib_ref/topic/p/posix_spawn.html
#[cfg(any(target_os = "nto", target_os = "qnx"))]
unsafe fn retrying_libc_posix_spawnp(
pid: *mut pid_t,
Expand Down Expand Up @@ -756,7 +756,7 @@ impl Command {
if self.get_setsid() {
cfg_select! {
all(target_os = "linux", target_env = "gnu") => {
flags |= libc::POSIX_SPAWN_SETSID;
flags |= libc::POSIX_SPAWN_SETSID as i32;
}
_ => {
return Ok(None);
Expand Down
9 changes: 5 additions & 4 deletions library/std/src/sys/thread/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> {

Ok(unsafe { NonZero::new_unchecked(cpus as usize) })
}
target_os = "nto" => {
any(target_os = "nto", target_os = "qnx") => {
unsafe {
use libc::_syspage_ptr;
if _syspage_ptr.is_null() {
Expand Down Expand Up @@ -347,7 +347,7 @@ pub fn current_os_id() -> Option<u64> {
let id: libc::pid_t = unsafe { gettid() };
Some(id as u64)
}
target_os = "nto" => {
any(target_os = "nto", target_os = "qnx") => {
// SAFETY: FFI call with no preconditions.
let id: libc::pid_t = unsafe { libc::gettid() };
Some(id as u64)
Expand Down Expand Up @@ -392,6 +392,7 @@ pub fn current_os_id() -> Option<u64> {
#[cfg(any(
target_os = "linux",
target_os = "nto",
target_os = "qnx",
target_os = "solaris",
target_os = "illumos",
target_os = "vxworks",
Expand Down Expand Up @@ -484,14 +485,14 @@ pub fn set_name(name: &CStr) {
}
}

#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))]
#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto", target_os = "qnx"))]
pub fn set_name(name: &CStr) {
weak!(
fn pthread_setname_np(thread: libc::pthread_t, name: *const libc::c_char) -> libc::c_int;
);

if let Some(f) = pthread_setname_np.get() {
#[cfg(target_os = "nto")]
#[cfg(any(target_os = "nto", target_os = "qnx"))]
const THREAD_NAME_MAX: usize = libc::_NTO_THREAD_NAME_MAX as usize;
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
const THREAD_NAME_MAX: usize = 32;
Expand Down
8 changes: 4 additions & 4 deletions library/std/src/sys/thread_local/key/racy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ pub struct LazyKey {

// Define a sentinel value that is likely not to be returned
// as a TLS key.
#[cfg(not(target_os = "nto"))]
#[cfg(not(any(target_os = "nto", target_os = "qnx")))]
const KEY_SENTVAL: usize = 0;
// On QNX Neutrino, 0 is always returned when currently not in use.
// Using 0 would mean to always create two keys and remote the first
// On QNX SDP, 0 is always returned when currently not in use.
// Using 0 would mean to always create two keys and remove the first
// one (with value of 0) immediately afterwards.
#[cfg(target_os = "nto")]
#[cfg(any(target_os = "nto", target_os = "qnx"))]
const KEY_SENTVAL: usize = libc::PTHREAD_KEYS_MAX + 1;

impl LazyKey {
Expand Down
12 changes: 6 additions & 6 deletions src/doc/rustc/src/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,9 @@ target | std | host | notes
[`aarch64-unknown-linux-pauthtest`](platform-support/aarch64-unknown-linux-pauthtest.md) | ✓ | ✓ | ARM64 PAC ELF ABI
[`aarch64-unknown-managarm-mlibc`](platform-support/managarm.md) | ? | | ARM64 Managarm
[`aarch64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD
[`aarch64-unknown-nto-qnx700`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.0 RTOS |
[`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS with default network stack (io-pkt) |
[`aarch64-unknown-nto-qnx710_iosock`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS with new network stack (io-sock) |
[`aarch64-unknown-nto-qnx700`](platform-support/nto-qnx.md) | ? | | ARM64 QNX SDP 7.0 |
[`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX SDP 7.1 with default network stack (io-pkt) |
[`aarch64-unknown-nto-qnx710_iosock`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX SDP 7.1 with new network stack (io-sock) |
[`aarch64-unknown-qnx`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX SDP 8.0+ |
[`aarch64-unknown-nuttx`](platform-support/nuttx.md) | ✓ | | ARM64 with NuttX
[`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD
Expand Down Expand Up @@ -340,7 +340,7 @@ target | std | host | notes
[`i586-unknown-redox`](platform-support/redox.md) | ✓ | | 32-bit x86 Redox OS (PentiumPro) [^x86_32-floats-x87]
[`i686-apple-darwin`](platform-support/apple-darwin.md) | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+, Penryn) [^x86_32-floats-return-ABI]
[`i686-oe-linux-gnu`](platform-support/oe-linux-gnu.md) | ✓ | | 32-bit x86 OpenEmbedded/Yocto Linux (GNU)
[`i686-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS (Pentium 4) [^x86_32-floats-return-ABI]
[`i686-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX SDP 7.0 (Pentium 4) [^x86_32-floats-return-ABI]
`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku (Pentium 4) [^x86_32-floats-return-ABI]
[`i686-unknown-helenos`](platform-support/helenos.md) | ✓ | | HelenOS IA-32 (see docs for pending issues)
[`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd (Pentium 4) [^x86_32-floats-return-ABI]
Expand Down Expand Up @@ -449,8 +449,8 @@ target | std | host | notes
[`x86_64-lynx-lynxos178`](platform-support/lynxos178.md) | | | x86_64 LynxOS-178
[`x86_64-oe-linux-gnu`](platform-support/oe-linux-gnu.md) | ✓ | | x86 64-bit OpenEmbedded/Yocto Linux (GNU)
[`x86_64-pc-cygwin`](platform-support/x86_64-pc-cygwin.md) | ✓ | | 64-bit x86 Cygwin |
[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS with default network stack (io-pkt) |
[`x86_64-pc-nto-qnx710_iosock`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS with new network stack (io-sock) |
[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX SDP 7.1 with default network stack (io-pkt) |
[`x86_64-pc-nto-qnx710_iosock`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX SDP 7.1 with new network stack (io-sock) |
[`x86_64-pc-qnx`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX SDP 8.0+ |
[`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ | | 64-bit Unikraft with musl 1.2.5
`x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD
Expand Down
Loading
Loading