Skip to content

Commit ced01a5

Browse files
authored
Use weakcall for eventfd on FreeBSD. (#718)
* Use `weakcall` for `eventfd` on FreeBSD. `eventfd` was introduced in FreeBSD 13, so it isn't in FreeBSD 12. Use `weakcall` to call it on FreeBSD so that we don't have a link-time dependency on it. Fixes #716. * Re-introduce FreeBSD 12 in the Cirrus CI config. FreeBSD 12 was origally removed in #517 due to problems with `curl`, however those were fixed by removing the `pkg install -y curl` in #643, so we can now re-enable FreeBSD 12 testing. * Use `weakcall!` for `ptsname_r` on FreeBSD too. FreeBSD 12 lacks `ptsname_r`. * Relax a test to accept `NOSYS` from `eventfd` on FreeBSD. * Relax some `procctl` tests on FreeBSD too. * Fix the `openpty` tests for FreeBSD 12.
1 parent e4a3a43 commit ced01a5

File tree

6 files changed

+85
-23
lines changed

6 files changed

+85
-23
lines changed

.cirrus.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,16 @@ task:
1313
test_script:
1414
- . $HOME/.cargo/env
1515
- cargo test --workspace --features=all-apis
16+
17+
task:
18+
name: stable x86_64-unknown-freebsd-12
19+
freebsd_instance:
20+
image_family: freebsd-12-1
21+
setup_script:
22+
- curl https://sh.rustup.rs -sSf --output rustup.sh
23+
- sh rustup.sh --default-toolchain stable -y --profile=minimal
24+
- . $HOME/.cargo/env
25+
- rustup default stable
26+
test_script:
27+
- . $HOME/.cargo/env
28+
- cargo test --workspace --features=all-apis

src/backend/libc/io/syscalls.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,22 @@ pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd>
282282

283283
#[cfg(any(target_os = "freebsd", target_os = "illumos"))]
284284
pub(crate) fn eventfd(initval: u32, flags: EventfdFlags) -> io::Result<OwnedFd> {
285-
unsafe { ret_owned_fd(c::eventfd(initval, flags.bits())) }
285+
// `eventfd` was added in FreeBSD 13, so it isn't available on FreeBSD 12.
286+
#[cfg(target_os = "freebsd")]
287+
unsafe {
288+
weakcall! {
289+
fn eventfd(
290+
initval: c::c_uint,
291+
flags: c::c_int
292+
) -> c::c_int
293+
}
294+
ret_owned_fd(eventfd(initval, flags.bits()))
295+
}
296+
297+
#[cfg(target_os = "illumos")]
298+
unsafe {
299+
ret_owned_fd(c::eventfd(initval, flags.bits()))
300+
}
286301
}
287302

288303
#[cfg(linux_kernel)]

src/backend/libc/pty/syscalls.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,27 @@ pub(crate) fn ptsname(fd: BorrowedFd, mut buffer: Vec<u8>) -> io::Result<CString
3131

3232
loop {
3333
// On platforms with `ptsname_r`, use it.
34-
#[cfg(any(target_os = "freebsd", linux_like, target_os = "fuchsia"))]
34+
#[cfg(any(linux_like, target_os = "fuchsia"))]
3535
let r =
3636
unsafe { libc::ptsname_r(borrowed_fd(fd), buffer.as_mut_ptr().cast(), buffer.len()) };
3737

38+
// FreeBSD 12 doesn't have `ptsname_r`.
39+
#[cfg(target_os = "freebsd")]
40+
let r = unsafe {
41+
weak! {
42+
fn ptsname_r(
43+
c::c_int,
44+
*mut c::c_char,
45+
c::size_t
46+
) -> c::c_int
47+
}
48+
if let Some(func) = ptsname_r.get() {
49+
func(borrowed_fd(fd), buffer.as_mut_ptr().cast(), buffer.len())
50+
} else {
51+
libc::ENOSYS
52+
}
53+
};
54+
3855
// MacOS 10.13.4 has `ptsname_r`; use it if we have it, otherwise fall
3956
// back to calling the underlying ioctl directly.
4057
#[cfg(apple)]

tests/io/eventfd.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ fn test_eventfd() {
55
use std::mem::size_of;
66
use std::thread;
77

8-
let efd = eventfd(0, EventfdFlags::CLOEXEC).unwrap();
8+
let efd = match eventfd(0, EventfdFlags::CLOEXEC) {
9+
Ok(efd) => efd,
10+
#[cfg(target_os = "freebsd")]
11+
Err(rustix::io::Errno::NOSYS) => return, // FreeBSD 12 lacks `eventfd`
12+
Err(e) => Err(e).unwrap(),
13+
};
914

1015
let child = thread::spawn(move || {
1116
for u in [1_u64, 3, 6, 11, 5000].iter() {

tests/process/procctl.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ fn test_trace_status() {
1313

1414
#[test]
1515
fn test_reaper_status() {
16-
assert_eq!(set_reaper_status(false), Err(io::Errno::INVAL));
16+
match set_reaper_status(false).unwrap_err() {
17+
io::Errno::INVAL => (),
18+
io::Errno::PERM => return, // FreeBSD 12 doesn't support this
19+
err => Err(err).unwrap(),
20+
};
1721
set_reaper_status(true).unwrap();
1822
let status_while_acq = dbg!(get_reaper_status(None).unwrap());
1923
set_reaper_status(false).unwrap();
@@ -38,7 +42,11 @@ fn test_trapcap() {
3842

3943
#[test]
4044
fn test_no_new_privs() {
41-
assert!(!no_new_privs(None).unwrap());
45+
match no_new_privs(None) {
46+
Ok(flag) => assert!(!flag),
47+
Err(io::Errno::INVAL) => return, // FreeBSD 12 doesn't support this
48+
Err(err) => Err(err).unwrap(),
49+
};
4250
set_no_new_privs(None).unwrap();
4351
assert!(no_new_privs(None).unwrap());
4452
// No going back but, well, we're not gonna execute SUID binaries from the

tests/pty/openpty.rs

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,76 @@
11
use rustix::fs::{cwd, openat, Mode, OFlags};
22
use rustix::pty::*;
33
use std::fs::File;
4-
use std::io;
54
use std::io::{Read, Write};
65

76
#[test]
8-
fn openpty_basic() -> io::Result<()> {
7+
fn openpty_basic() {
98
// Use `CLOEXEC` if we can.
109
#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "netbsd"))]
1110
let flags = OpenptFlags::RDWR | OpenptFlags::NOCTTY | OpenptFlags::CLOEXEC;
1211
#[cfg(not(any(linux_kernel, target_os = "freebsd", target_os = "netbsd")))]
1312
let flags = OpenptFlags::RDWR | OpenptFlags::NOCTTY;
1413

15-
let controller = openpt(flags)?;
14+
let controller = openpt(flags).unwrap();
1615

17-
grantpt(&controller)?;
18-
unlockpt(&controller)?;
16+
grantpt(&controller).unwrap();
17+
unlockpt(&controller).unwrap();
1918

20-
let name = ptsname(&controller, Vec::new())?;
19+
let name = match ptsname(&controller, Vec::new()) {
20+
Ok(name) => name,
21+
#[cfg(target_os = "freebsd")]
22+
Err(rustix::io::Errno::NOSYS) => return, // FreeBSD 12 doesn't support this
23+
Err(err) => Err(err).unwrap(),
24+
};
2125
let user = openat(
2226
cwd(),
2327
name,
2428
OFlags::RDWR | OFlags::NOCTTY | OFlags::CLOEXEC,
2529
Mode::empty(),
26-
)?;
30+
)
31+
.unwrap();
2732

2833
let mut controller = File::from(controller);
2934
let mut user = File::from(user);
3035

3136
// The '\x04' is Ctrl-D, the default EOF control code.
32-
controller.write_all(b"Hello, world!\n\x04")?;
37+
controller.write_all(b"Hello, world!\n\x04").unwrap();
3338

3439
let mut s = String::new();
35-
user.read_to_string(&mut s)?;
40+
user.read_to_string(&mut s).unwrap();
3641

3742
assert_eq!(s, "Hello, world!\n");
38-
Ok(())
3943
}
4044

4145
// Like `openpty_basic` but use `ioctl_tiocgptpeer` instead of `ptsname`.
4246
#[cfg(target_os = "linux")]
4347
#[test]
44-
fn openpty_get_peer() -> io::Result<()> {
48+
fn openpty_get_peer() {
4549
// Use `CLOEXEC` if we can.
4650
#[cfg(any(linux_kernel, target_os = "freebsd", target_os = "netbsd"))]
4751
let flags = OpenptFlags::RDWR | OpenptFlags::NOCTTY | OpenptFlags::CLOEXEC;
4852
#[cfg(not(any(linux_kernel, target_os = "freebsd", target_os = "netbsd")))]
4953
let flags = OpenptFlags::RDWR | OpenptFlags::NOCTTY;
5054

51-
let controller = openpt(flags)?;
55+
let controller = openpt(flags).unwrap();
5256

53-
grantpt(&controller)?;
54-
unlockpt(&controller)?;
57+
grantpt(&controller).unwrap();
58+
unlockpt(&controller).unwrap();
5559

5660
let user = ioctl_tiocgptpeer(
5761
&controller,
5862
OpenptFlags::RDWR | OpenptFlags::NOCTTY | OpenptFlags::CLOEXEC,
59-
)?;
63+
)
64+
.unwrap();
6065

6166
let mut controller = File::from(controller);
6267
let mut user = File::from(user);
6368

6469
// The '\x04' is Ctrl-D, the default EOF control code.
65-
controller.write_all(b"Hello, world!\n\x04")?;
70+
controller.write_all(b"Hello, world!\n\x04").unwrap();
6671

6772
let mut s = String::new();
68-
user.read_to_string(&mut s)?;
73+
user.read_to_string(&mut s).unwrap();
6974

7075
assert_eq!(s, "Hello, world!\n");
71-
Ok(())
7276
}

0 commit comments

Comments
 (0)