diff --git a/common/channel.cc b/common/channel.cc index ef4ea19..787e9f4 100644 --- a/common/channel.cc +++ b/common/channel.cc @@ -401,7 +401,14 @@ Channel::PosixSharedMemoryName(const std::string &shadow_file) { // Use the inode number (unique per file) to make the shm file name. // st_ino is unsigned and can be 64-bit on some systems (e.g. QNX), so // promote to uint64_t before formatting. - return absl::StrFormat("subspace_%llu", + // + // The leading '/' is required: POSIX shm_open names that do not start with + // '/' are implementation-defined. On QNX they resolve relative to the + // process cwd, so a publisher started under + // /applications/install/opt// creates objects that a subscriber + // started from '/' cannot open (ENOENT). A leading slash places the object + // in the global shm namespace (macOS also requires a leading '/'). + return absl::StrFormat("/subspace_%llu", static_cast(st.st_ino)); } #endif diff --git a/rust_client/src/publisher.rs b/rust_client/src/publisher.rs index 0d96a7f..f69b1d3 100644 --- a/rust_client/src/publisher.rs +++ b/rust_client/src/publisher.rs @@ -880,7 +880,9 @@ fn create_shm(name: &str, size: usize) -> crate::error::Result { #[cfg(not(target_os = "linux"))] fn posix_shm_name(shadow_path: &str) -> crate::error::Result { let stat = crate::syscall_shim::shim_stat(shadow_path)?; - Ok(format!("subspace_{}", stat.st_ino)) + // POSIX shm names must use the global namespace so Rust and C++ clients + // resolve the same object even when their working directories differ. + Ok(format!("/subspace_{}", stat.st_ino)) } #[cfg(not(target_os = "linux"))]