Skip to content

Commit 9c522fd

Browse files
authored
Fix the size of FdSetElement on 32-bit Windows. (#1381)
On rustix on Windows, `RawFd` is `SOCKET`, which is the size of `usize`, so make `FdSet` 32-bit on 32-bitt Windows to match it.
1 parent 156e6f4 commit 9c522fd

File tree

9 files changed

+26
-26
lines changed

9 files changed

+26
-26
lines changed

.github/workflows/main.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ jobs:
8282
sparcv9-sun-solaris
8383
aarch64-linux-android
8484
aarch64-apple-ios
85+
i686-pc-windows-msvc
8586
- if: matrix.rust != '1.63'
8687
run: >
8788
rustup target add
@@ -132,6 +133,7 @@ jobs:
132133
- run: cargo check --workspace --release -vv --target=sparcv9-sun-solaris --features=all-apis --all-targets
133134
- run: cargo check --workspace --release -vv --target=aarch64-apple-ios --features=all-apis --all-targets
134135
- run: cargo check --workspace --release -vv --target=aarch64-linux-android --features=all-apis --all-targets
136+
- run: cargo check --workspace --release -vv --target=i686-pc-windows-msvc --features=all-apis --all-targets
135137

136138
check_no_default_features:
137139
name: Check --no-default-features

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ memoffset = "0.9.0"
7373
flate2 = "1.0"
7474
static_assertions = "1.1.0"
7575

76+
# With Rust 1.70 this can be removed in favor of `std::sync::OnceLock`.
77+
[target.'cfg(windows)'.dev-dependencies]
78+
once_cell = "1.20.3"
79+
7680
[target.'cfg(all(criterion, not(any(target_os = "emscripten", target_os = "wasi"))))'.dev-dependencies]
7781
criterion = "0.4"
7882

src/backend/libc/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,11 @@ pub(crate) mod fd {
7979
/// [`AsFd`]: https://doc.rust-lang.org/stable/std/os/fd/trait.AsFd.html
8080
pub trait AsFd {
8181
/// An `as_fd` function for Winsock, where an `Fd` is a `Socket`.
82-
fn as_fd(&self) -> BorrowedFd;
82+
fn as_fd(&self) -> BorrowedFd<'_>;
8383
}
8484
impl<T: AsSocket> AsFd for T {
8585
#[inline]
86-
fn as_fd(&self) -> BorrowedFd {
86+
fn as_fd(&self) -> BorrowedFd<'_> {
8787
self.as_socket()
8888
}
8989
}

src/backend/libc/net/sockopt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1002,7 +1002,7 @@ pub(crate) fn tcp_congestion(fd: BorrowedFd<'_>) -> io::Result<String> {
10021002
unsafe {
10031003
let value = value.assume_init();
10041004
let slice: &[u8] = core::mem::transmute(&value[..optlen as usize]);
1005-
assert!(slice.iter().any(|b| *b == b'\0'));
1005+
assert!(slice.contains(&b'\0'));
10061006
Ok(
10071007
core::str::from_utf8(CStr::from_ptr(slice.as_ptr().cast()).to_bytes())
10081008
.unwrap()

src/backend/linux_raw/net/sockopt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,7 @@ pub(crate) fn tcp_congestion(fd: BorrowedFd<'_>) -> io::Result<String> {
809809
unsafe {
810810
let value = value.assume_init();
811811
let slice: &[u8] = core::mem::transmute(&value[..optlen as usize]);
812-
assert!(slice.iter().any(|b| *b == b'\0'));
812+
assert!(slice.contains(&b'\0'));
813813
Ok(
814814
core::str::from_utf8(CStr::from_ptr(slice.as_ptr().cast()).to_bytes())
815815
.unwrap()

src/event/select.rs

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ use crate::{backend, io};
1313
#[cfg(any(windows, target_os = "wasi"))]
1414
use core::mem::align_of;
1515
use core::mem::size_of;
16-
#[cfg(any(windows, target_os = "wasi"))]
17-
use core::slice;
1816

1917
/// wasi-libc's `fd_set` type. The libc bindings for it have private fields, so
2018
/// we redeclare it for ourselves so that we can access the fields. They're
@@ -32,12 +30,9 @@ struct FD_SET {
3230
use windows_sys::Win32::Networking::WinSock::FD_SET;
3331

3432
/// Storage element type for use with [`select`].
35-
#[cfg(any(
36-
windows,
37-
all(
38-
target_pointer_width = "64",
39-
any(target_os = "freebsd", target_os = "dragonfly")
40-
)
33+
#[cfg(all(
34+
target_pointer_width = "64",
35+
any(windows, target_os = "freebsd", target_os = "dragonfly")
4136
))]
4237
#[repr(transparent)]
4338
#[derive(Copy, Clone, Default)]
@@ -52,11 +47,10 @@ pub struct FdSetElement(pub(crate) c::c_ulong);
5247
/// Storage element type for use with [`select`].
5348
#[cfg(not(any(
5449
linux_like,
55-
windows,
5650
target_os = "wasi",
5751
all(
5852
target_pointer_width = "64",
59-
any(target_os = "freebsd", target_os = "dragonfly")
53+
any(windows, target_os = "freebsd", target_os = "dragonfly")
6054
)
6155
)))]
6256
#[repr(transparent)]
@@ -145,12 +139,10 @@ pub fn fd_set_insert(fds: &mut [FdSetElement], fd: RawFd) {
145139
{
146140
let set = unsafe { &mut *fds.as_mut_ptr().cast::<FD_SET>() };
147141
let fd_count = set.fd_count;
148-
let fd_array = unsafe { slice::from_raw_parts(set.fd_array.as_ptr(), fd_count as usize) };
142+
let fd_array = &set.fd_array[..fd_count as usize];
149143

150-
if !fd_array.iter().any(|p| *p as RawFd == fd) {
151-
let fd_array = unsafe {
152-
slice::from_raw_parts_mut(set.fd_array.as_mut_ptr(), fd_count as usize + 1)
153-
};
144+
if !fd_array.contains(&(fd as _)) {
145+
let fd_array = &mut set.fd_array[..fd_count as usize + 1];
154146
set.fd_count = fd_count + 1;
155147
fd_array[fd_count as usize] = fd as _;
156148
}
@@ -171,7 +163,7 @@ pub fn fd_set_remove(fds: &mut [FdSetElement], fd: RawFd) {
171163
{
172164
let set = unsafe { &mut *fds.as_mut_ptr().cast::<FD_SET>() };
173165
let fd_count = set.fd_count;
174-
let fd_array = unsafe { slice::from_raw_parts(set.fd_array.as_ptr(), fd_count as usize) };
166+
let fd_array = &set.fd_array[..fd_count as usize];
175167

176168
if let Some(pos) = fd_array.iter().position(|p| *p as RawFd == fd) {
177169
set.fd_count = fd_count - 1;
@@ -197,7 +189,7 @@ pub fn fd_set_bound(fds: &[FdSetElement]) -> RawFd {
197189
{
198190
let set = unsafe { &*fds.as_ptr().cast::<FD_SET>() };
199191
let fd_count = set.fd_count;
200-
let fd_array = unsafe { slice::from_raw_parts(set.fd_array.as_ptr(), fd_count as usize) };
192+
let fd_array = &set.fd_array[..fd_count as usize];
201193
let mut max = 0;
202194
for fd in fd_array {
203195
if *fd >= max {
@@ -334,7 +326,7 @@ impl<'a> Iterator for FdSetIter<'a> {
334326

335327
let set = unsafe { &*self.fds.as_ptr().cast::<FD_SET>() };
336328
let fd_count = set.fd_count;
337-
let fd_array = unsafe { slice::from_raw_parts(set.fd_array.as_ptr(), fd_count as usize) };
329+
let fd_array = &set.fd_array[..fd_count as usize];
338330

339331
if current == fd_count as usize {
340332
return None;

tests/event/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ mod select;
2121

2222
#[cfg(windows)]
2323
mod windows {
24-
use std::sync::OnceLock;
24+
// With Rust 1.70 this can be `std::sync::OnceLock`.
25+
use once_cell::sync::OnceCell as OnceLock;
2526

2627
pub struct Thing;
2728

tests/event/select.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ fn test_select_with_great_fds() {
104104
}
105105
setrlimit(Resource::Nofile, rlimit).unwrap();
106106

107-
// Create a fd at `FD_SETSIZE + 1` out of thin air. Use `libc` instead of
108-
// `OwnedFd::from_raw_fd` because grabbing a fd out of thin air violates
107+
// Create an fd at `FD_SETSIZE + 1` out of thin air. Use `libc` instead of
108+
// `OwnedFd::from_raw_fd` because grabbing an fd out of thin air violates
109109
// Rust's concept of I/O safety (and wouldn't make sense to do in anything
110110
// other than a test like this).
111111
let great_fd = unsafe { libc::dup2(reader.as_raw_fd(), libc::FD_SETSIZE as RawFd + 1) };

tests/net/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ mod v6;
2626

2727
#[cfg(windows)]
2828
mod windows {
29-
use std::sync::OnceLock;
29+
// With Rust 1.70 this can be `std::sync::OnceLock`.
30+
use once_cell::sync::OnceCell as OnceLock;
3031

3132
pub struct Thing;
3233

0 commit comments

Comments
 (0)