Skip to content

Commit 5b9f52a

Browse files
committed
Support the optional "close" feature on Windows.
Disabling the "close" feature makes io-lifetimes not depend on calling `CloseHandle` or `closesocket`, so that it can sit underneath syscall wrapping libraries which provide those functions.
1 parent 2d2299f commit 5b9f52a

File tree

5 files changed

+48
-7
lines changed

5 files changed

+48
-7
lines changed

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ fs-err = { version = "2.6.0", optional = true }
3636
libc = { version = "0.2.96", optional = true }
3737

3838
[target.'cfg(windows)'.dependencies]
39-
winapi = { version = "0.3.9", features = ["handleapi", "std", "winsock2"] }
39+
winapi = { version = "0.3.9", optional = true, features = ["handleapi", "std", "winsock2"] }
4040

4141
[features]
4242
default = ["close"]
43-
close = ["libc"]
43+
close = ["libc", "winapi"]

examples/hello.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ fn main() -> io::Result<()> {
5959
}
6060

6161
/// The Windows analog of the above.
62-
#[cfg(windows)]
62+
#[cfg(all(windows, feature = "close"))]
6363
fn main() -> io::Result<()> {
6464
let handle = unsafe {
6565
// Open a file, which returns an `HandleOrInvalid`, which we can fallibly
@@ -120,7 +120,10 @@ fn main() -> io::Result<()> {
120120
Ok(())
121121
}
122122

123-
#[cfg(all(not(all(rustc_attrs, unix, feature = "close")), not(windows)))]
123+
#[cfg(all(
124+
not(all(rustc_attrs, unix, feature = "close")),
125+
not(all(windows, feature = "close"))
126+
))]
124127
fn main() {
125128
println!("On Unix, this example requires Rust nightly (for `rustc_attrs`) and the \"close\" feature.");
126129
}

src/example_ffi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub use libc::{O_CLOEXEC, O_CREAT, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY};
3838
/// the return type for `CreateFileW`, since that function is defined to return
3939
/// [`INVALID_HANDLE_VALUE`] on error instead of null.
4040
#[cfg(windows)]
41-
extern "C" {
41+
extern "system" {
4242
pub fn CreateFileW(
4343
lpFileName: LPCWSTR,
4444
dwDesiredAccess: DWORD,

src/types.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,14 @@ use std::{
1313
RawHandle, RawSocket,
1414
},
1515
};
16-
#[cfg(windows)]
16+
#[cfg(all(windows, feature = "close"))]
1717
use winapi::{um::handleapi::INVALID_HANDLE_VALUE, um::winsock2::INVALID_SOCKET};
1818

19+
#[cfg(all(windows, not(feature = "winapi")))]
20+
const INVALID_HANDLE_VALUE: *mut core::ffi::c_void = !0 as _;
21+
#[cfg(all(windows, not(feature = "winapi")))]
22+
const INVALID_SOCKET: usize = !0 as _;
23+
1924
/// A borrowed file descriptor.
2025
///
2126
/// This has a lifetime parameter to tie it to the lifetime of something that
@@ -488,39 +493,71 @@ impl Drop for OwnedFd {
488493
impl Drop for OwnedHandle {
489494
#[inline]
490495
fn drop(&mut self) {
496+
#[cfg(feature = "close")]
491497
unsafe {
492498
let _ = winapi::um::handleapi::CloseHandle(self.handle);
493499
}
500+
501+
// If the `close` feature is disabled, we expect users to avoid letting
502+
// `OwnedHandle` instances drop, so that we don't have to call `close`.
503+
#[cfg(not(feature = "close"))]
504+
{
505+
unreachable!("drop called without the \"close\" feature in io-lifetimes");
506+
}
494507
}
495508
}
496509

497510
#[cfg(windows)]
498511
impl Drop for HandleOrInvalid {
499512
#[inline]
500513
fn drop(&mut self) {
514+
#[cfg(feature = "close")]
501515
unsafe {
502516
let _ = winapi::um::handleapi::CloseHandle(self.0);
503517
}
518+
519+
// If the `close` feature is disabled, we expect users to avoid letting
520+
// `HandleOrInvalid` instances drop, so that we don't have to call `close`.
521+
#[cfg(not(feature = "close"))]
522+
{
523+
unreachable!("drop called without the \"close\" feature in io-lifetimes");
524+
}
504525
}
505526
}
506527

507528
#[cfg(windows)]
508529
impl Drop for HandleOrNull {
509530
#[inline]
510531
fn drop(&mut self) {
532+
#[cfg(feature = "close")]
511533
unsafe {
512534
let _ = winapi::um::handleapi::CloseHandle(self.0);
513535
}
536+
537+
// If the `close` feature is disabled, we expect users to avoid letting
538+
// `HandleOrNull` instances drop, so that we don't have to call `close`.
539+
#[cfg(not(feature = "close"))]
540+
{
541+
unreachable!("drop called without the \"close\" feature in io-lifetimes");
542+
}
514543
}
515544
}
516545

517546
#[cfg(windows)]
518547
impl Drop for OwnedSocket {
519548
#[inline]
520549
fn drop(&mut self) {
550+
#[cfg(feature = "close")]
521551
unsafe {
522552
let _ = winapi::um::winsock2::closesocket(self.socket as winapi::um::winsock2::SOCKET);
523553
}
554+
555+
// If the `close` feature is disabled, we expect users to avoid letting
556+
// `OwnedSocket` instances drop, so that we don't have to call `close`.
557+
#[cfg(not(feature = "close"))]
558+
{
559+
unreachable!("drop called without the \"close\" feature in io-lifetimes");
560+
}
524561
}
525562
}
526563

tests/assumptions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
22

3+
#[cfg(any(not(windows), feature = "close"))]
34
use std::mem::size_of;
45

56
#[cfg(unix)]
@@ -22,7 +23,7 @@ fn test_assumptions() {
2223
);
2324
}
2425

25-
#[cfg(windows)]
26+
#[cfg(all(windows, feature = "close"))]
2627
#[test]
2728
fn test_assumptions() {
2829
assert_eq!(

0 commit comments

Comments
 (0)