Skip to content

Allow cargo test to complete on OpenBSD 6.4/AMD64 #1001

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
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
2 changes: 1 addition & 1 deletion src/sys/stat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ pub fn utimes<P: ?Sized + NixPath>(path: &P, atime: &TimeVal, mtime: &TimeVal) -
/// # References
///
/// [lutimes(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lutimes.html).
#[cfg(not(target_os = "android"))]
#[cfg(not(any(target_os = "android", target_os = "openbsd")))]
pub fn lutimes<P: ?Sized + NixPath>(path: &P, atime: &TimeVal, mtime: &TimeVal) -> Result<()> {
let times: [libc::timeval; 2] = [*atime.as_ref(), *mtime.as_ref()];
let res = path.with_nix_path(|cstr| unsafe {
Expand Down
3 changes: 1 addition & 2 deletions src/unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -763,8 +763,7 @@ pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<
#[cfg(any(target_os = "android",
target_os = "freebsd",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd"))]
target_os = "netbsd"))]
#[inline]
pub fn fexecve(fd: RawFd, args: &[CString], env: &[CString]) -> Result<Void> {
let args_p = to_exec_array(args);
Expand Down
12 changes: 6 additions & 6 deletions test/sys/test_aio_drop.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
extern crate nix;
extern crate tempfile;

use nix::sys::aio::*;
use nix::sys::signal::*;
use std::os::unix::io::AsRawFd;
use tempfile::tempfile;

// Test dropping an AioCb that hasn't yet finished.
// This must happen in its own process, because on OSX this test seems to hose
// the AIO subsystem and causes subsequent tests to fail
#[test]
#[should_panic(expected = "Dropped an in-progress AioCb")]
#[cfg(not(target_env = "musl"))]
#[cfg(not(any(target_env = "musl", target_os = "openbsd")))]
fn test_drop() {
use nix::sys::aio::*;
use nix::sys::signal::*;
use std::os::unix::io::AsRawFd;
use tempfile::tempfile;

const WBUF: &[u8] = b"CDEF";

let f = tempfile().unwrap();
Expand Down
1 change: 1 addition & 0 deletions test/sys/test_socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ pub fn test_socketpair() {
assert_eq!(&buf[..], b"hello");
}

#[cfg(not(any(target_os = "openbsd")))]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's wrong with this test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't try to diagnose the problem. I was just trying to get tests to pass so I could work on IP6_PKTINFO, IP_RECVIF, and IP_RECV_DSTADDR

failures:

---- sys::test_socket::test_scm_rights stdout ----
thread 'sys::test_socket::test_scm_rights' panicked at 'slice index starts at 24 but ends at 20', libcore/slice/mod.rs:1977:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be #999. If there's an alignment problem, off by 4 could happen.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's a stack trace with RUST_BACKTRACE=1

failures:

---- sys::test_socket::test_scm_rights stdout ----
thread 'sys::test_socket::test_scm_rights' panicked at 'slice index starts at 24 but ends at 20', libcore/slice/mod.rs:1977:5
stack backtrace:
   0: __register_frame_info
   1: __register_frame_info
   2: __register_frame_info
   3: __register_frame_info
   4: __register_frame_info
   5: __register_frame_info
   6: __register_frame_info
   7: __register_frame_info
   8: __register_frame_info
   9: __register_frame_info
  10: __register_frame_info
  11: __register_frame_info
  12: __register_frame_info
  13: __register_frame_info
  14: __register_frame_info
  15: __register_frame_info
  16: __register_frame_info
  17: __register_frame_info
  18: __register_frame_info
  19: __register_frame_info
  20: __register_frame_info
  21: __register_frame_info
  22: __register_frame_info
  23: __register_frame_info
  24: pthread_create


failures:
    sys::test_socket::test_scm_rights

test result: FAILED. 87 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When running the test as standalone code in a main(), I got a different stack trace:

% RUST_BACKTRACE=1 cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 4.53s
     Running `target/debug/scm_rights`
thread 'main' panicked at 'slice index starts at 24 but ends at 20', libcore/slice/mod.rs:1977:5
stack backtrace:
   0: __register_frame_info
   1: __register_frame_info
   2: __register_frame_info
   3: __register_frame_info
   4: __register_frame_info
   5: __register_frame_info
   6: __register_frame_info
   7: __register_frame_info
   8: __register_frame_info
   9: __register_frame_info
  10: __register_frame_info
  11: __register_frame_info
  12: __register_frame_info
  13: __register_frame_info
  14: __register_frame_info
  15: __register_frame_info
  16: __register_frame_info
  17: __register_frame_info
  18: __register_frame_info
  19: __register_frame_info
  20: <unknown>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think #999 is related. If anything, #999 should cause bus errors on platforms like mips that don't allow unaligned loads. This error looks more like we got some alignment stuff wrong in #648. When you encounter the bug, what is the address of the struct cmsghdr? If it's 4-byte aligned, then try putting the CmsgSpace in a Box. That should increase its alignment to 16 bytes. If that fixes the test, then we know where the problem lies.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks 16 byte aligned to me. On the sendmsg side:

(gdb) print cmsg
Python Exception <class 'gdb.error'> That operation is not available on integers of more than 8 bytes.: 
Python Exception <class 'gdb.error'> That operation is not available on integers of more than 8 bytes.: 
$1 = nix::sys::socket::ControlMessage::ScmRights(&[i32](len: 1) = {5})
(gdb) print &cmsg
$2 = (nix::sys::socket::ControlMessage *) 0x7f7ffffea920

On the recvmsg side:

28              let mut cmsgspace: CmsgSpace<[RawFd; 1]> = CmsgSpace::new();
(gdb) n
29              let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
(gdb) print &cmsgspace
$3 = (nix::sys::socket::CmsgSpace<[i32; 1]> *) 0x7f7ffffeaa60

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, there goes that theory. Maybe cmsg_align doesn't work correctly on OpenBSD? If you could reimplement the test in C, that might reveal where any alignment errors lie.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the unwrapped RecvMsg from recvmsg() is not 16 byte aligned:

Breakpoint 1, scm_rights::main::h34fb823cda0cd73f () at src/main.rs:34
34                  for cmsg in msg.cmsgs() {
(gdb) print msg
$1 = RecvMsg = {bytes = 5, cmsg_buffer = &[u8](len: 20) = {20, 0, 0, 0, 255, 
    255, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, Python Exception <class 'gdb.error'> Cannot convert value to int.: 
0}, 
  address = <error reading variable>, flags = MsgFlags = {bits = 0}}
(gdb) print &msg
$2 = (nix::sys::socket::RecvMsg *) 0x7f7fffff2838

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I can fix this particular error by setting align_of_cmsg_data = u32 on OpenBSD. But I don't have any theoretical reason for doing that, and it breaks the ScmTimestamp test. I think the best thing to do is to rewrite all of the cmsg code in terms of CMSG_DATA and friends, which are provided by libc.

#[test]
pub fn test_scm_rights() {
use nix::sys::uio::IoVec;
Expand Down
7 changes: 6 additions & 1 deletion test/test_stat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ use std::time::{Duration, UNIX_EPOCH};
use libc::{S_IFMT, S_IFLNK};

use nix::fcntl;
use nix::sys::stat::{self, fchmod, fchmodat, futimens, lutimes, stat, utimes, utimensat};
use nix::sys::stat::{self, fchmod, fchmodat, futimens, stat, utimes, utimensat};

#[cfg(not(any(target_os = "openbsd")))]
use nix::sys::stat::lutimes;

use nix::sys::stat::{Mode, FchmodatFlags, UtimensatFlags};

#[cfg(not(any(target_os = "netbsd")))]
Expand Down Expand Up @@ -196,6 +200,7 @@ fn test_utimes() {
}

#[test]
#[cfg(not(any(target_os = "openbsd")))]
fn test_lutimes() {
let tempdir = tempfile::tempdir().unwrap();
let target = tempdir.path().join("target");
Expand Down
8 changes: 4 additions & 4 deletions test/test_unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,16 +230,16 @@ cfg_if!{
execve_test_factory!(test_execve, execve, &CString::new("/system/bin/sh").unwrap());
execve_test_factory!(test_fexecve, fexecve, File::open("/system/bin/sh").unwrap().into_raw_fd());
} else if #[cfg(any(target_os = "freebsd",
target_os = "linux",
target_os = "openbsd"))] {
target_os = "linux"))] {
execve_test_factory!(test_execve, execve, &CString::new("/bin/sh").unwrap());
execve_test_factory!(test_fexecve, fexecve, File::open("/bin/sh").unwrap().into_raw_fd());
} else if #[cfg(any(target_os = "dragonfly",
target_os = "ios",
target_os = "macos",
target_os = "netbsd"))] {
target_os = "netbsd",
target_os = "openbsd"))] {
execve_test_factory!(test_execve, execve, &CString::new("/bin/sh").unwrap());
// No fexecve() on DragonFly, ios, macos, and NetBSD.
// No fexecve() on DragonFly, ios, macos, NetBSD or OpenBSD.
}
}

Expand Down