Skip to content

Commit 06194be

Browse files
committed
Add a way to use io-lifetimes without depending on libc.
Add a "close" feature, enabled by default, and only call `close` when this feature is enabled. If anyone attempts to drop an `OwnedFd` without this feature enabled, issue a link-time error.
1 parent 2627775 commit 06194be

File tree

8 files changed

+46
-13
lines changed

8 files changed

+46
-13
lines changed

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,14 @@ mio = { version = "0.7.11", features = ["net", "os-ext"], optional = true }
3636
fs-err = { version = "2.6.0", optional = true }
3737

3838
[target.'cfg(not(windows))'.dependencies]
39-
libc = "0.2.96"
39+
libc = { version = "0.2.96", optional = true }
4040

4141
[target.'cfg(windows)'.dependencies]
4242
winapi = { version = "0.3.9", features = ["handleapi", "std", "winsock2"] }
4343

44+
[features]
45+
default = ["close"]
46+
close = ["libc"]
47+
4448
[badges]
4549
maintenance = { status = "actively-developed" }

examples/flexible-apis.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//! The following uses the POSIX-ish `Fd` types; similar considerations
55
//! apply to the Windows and portable types.
66
7-
#[cfg(not(windows))]
7+
#[cfg(all(feature = "close", not(windows)))]
88
use io_lifetimes::{AsFd, BorrowedFd, IntoFd, OwnedFd};
99

1010
/// The simplest way to accept a borrowed I/O resource is to simply use a
@@ -15,7 +15,7 @@ use io_lifetimes::{AsFd, BorrowedFd, IntoFd, OwnedFd};
1515
///
1616
/// Callers with an `AsFd`-implementing type would call `.as_fd()` and pass
1717
/// the result.
18-
#[cfg(not(windows))]
18+
#[cfg(all(feature = "close", not(windows)))]
1919
fn use_fd_a(fd: BorrowedFd<'_>) {
2020
let _ = fd;
2121
}
@@ -24,7 +24,7 @@ fn use_fd_a(fd: BorrowedFd<'_>) {
2424
/// verbose at the function definition site, and entails monomorphization, but
2525
/// it has the advantage of allowing users to pass in any type implementing
2626
/// `AsFd` directly, without having to call `.as_fd()` themselves.
27-
#[cfg(not(windows))]
27+
#[cfg(all(feature = "close", not(windows)))]
2828
fn use_fd_b<Fd: AsFd>(fd: &Fd) {
2929
let _ = fd.as_fd();
3030
}
@@ -35,7 +35,7 @@ fn use_fd_b<Fd: AsFd>(fd: &Fd) {
3535
///
3636
/// Callers with an `IntoFd`-implementing type would call `.into_fd()` and pass
3737
/// the result.
38-
#[cfg(not(windows))]
38+
#[cfg(all(feature = "close", not(windows)))]
3939
fn consume_fd_a(fd: OwnedFd) {
4040
let _ = fd;
4141
}
@@ -44,13 +44,13 @@ fn consume_fd_a(fd: OwnedFd) {
4444
/// `use_fd_b`, this is more verbose here and entails monomorphization, but it
4545
/// has the advantage of allowing users to pass in any type implementing
4646
/// `IntoFd` directly.
47-
#[cfg(not(windows))]
47+
#[cfg(all(feature = "close", not(windows)))]
4848
fn consume_fd_b<Fd: IntoFd>(fd: Fd) {
4949
let _ = fd.into_fd();
5050
}
5151

5252
/// Now let's see how the APIs look for users.
53-
#[cfg(not(windows))]
53+
#[cfg(all(feature = "close", not(windows)))]
5454
fn main() {
5555
let f = std::fs::File::open("Cargo.toml").unwrap();
5656

@@ -77,3 +77,8 @@ fn main() {
7777
fn main() {
7878
println!("This example uses non-Windows APIs.");
7979
}
80+
81+
#[cfg(all(not(feature = "close"), not(windows)))]
82+
fn main() {
83+
println!("This example requires the \"close\" feature.");
84+
}

examples/hello.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,23 @@
33
44
#![cfg_attr(not(rustc_attrs), allow(unused_imports))]
55

6+
#[cfg(feature = "close")]
67
use io_lifetimes::example_ffi::*;
7-
use std::fs::File;
8-
use std::io::{self, Write};
8+
#[cfg(feature = "close")]
9+
use std::{
10+
fs::File,
11+
io::{self, Write},
12+
};
913

10-
#[cfg(unix)]
14+
#[cfg(all(unix, feature = "close"))]
1115
use io_lifetimes::{AsFd, FromFd, IntoFd, OwnedFd};
1216

1317
#[cfg(windows)]
1418
use io_lifetimes::{AsHandle, FromHandle, IntoHandle, OwnedHandle};
1519
#[cfg(windows)]
1620
use std::{convert::TryInto, ptr::null_mut};
1721

18-
#[cfg(all(rustc_attrs, unix))]
22+
#[cfg(all(rustc_attrs, unix, feature = "close"))]
1923
fn main() -> io::Result<()> {
2024
let fd = unsafe {
2125
// Open a file, which returns an `Option<OwnedFd>`, which we can
@@ -131,7 +135,7 @@ fn main() -> io::Result<()> {
131135
Ok(())
132136
}
133137

134-
#[cfg(not(any(windows, rustc_attrs)))]
138+
#[cfg(all(not(all(rustc_attrs, unix, feature = "close")), not(windows)))]
135139
fn main() {
136-
println!("On Unix, this example requires Rust nightly (for `rustc_attrs`).");
140+
println!("On Unix, this example requires Rust nightly (for `rustc_attrs`) and the \"close\" feature.");
137141
}

examples/owning-wrapper.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ impl FromHandle for Thing {
7171
}
7272
}
7373

74+
#[cfg(feature = "close")]
7475
fn main() {
7576
use io_lifetimes::{AsFilelike, FromFilelike, IntoFilelike};
7677

@@ -101,3 +102,8 @@ fn main() {
101102
let _ = thing.into_filelike();
102103
}
103104
}
105+
106+
#[cfg(not(feature = "close"))]
107+
fn main() {
108+
println!("This example requires the \"close\" feature.");
109+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ pub use portability::{
5050
IntoFilelike, IntoSocketlike, OwnedFilelike, OwnedSocketlike,
5151
};
5252

53+
#[cfg(feature = "close")]
5354
pub mod example_ffi;
5455
pub mod views;
5556

src/types.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,9 +440,20 @@ impl FromRawHandle for OptionFileHandle {
440440
impl Drop for OwnedFd {
441441
#[inline]
442442
fn drop(&mut self) {
443+
#[cfg(feature = "close")]
443444
unsafe {
444445
let _ = libc::close(self.raw as std::os::raw::c_int);
445446
}
447+
448+
// If the `close` feature is disabled, we expect users to avoid letting
449+
// `OwnedFd` instances drop, so that we don't have to call `close`.
450+
#[cfg(not(feature = "close"))]
451+
unsafe {
452+
extern "C" {
453+
fn __drop_called_without_the_close_feature();
454+
}
455+
__drop_called_without_the_close_feature();
456+
}
446457
}
447458
}
448459

tests/api.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
2+
#![cfg(feature = "close")]
23

34
use io_lifetimes::{
45
AsFilelike, AsSocketlike, BorrowedFilelike, FromFilelike, FromSocketlike, IntoFilelike,

tests/ffi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![cfg_attr(not(rustc_attrs), allow(unused_imports))]
2+
#![cfg(feature = "close")]
23

34
#[cfg(any(unix, windows))]
45
use io_lifetimes::example_ffi::*;

0 commit comments

Comments
 (0)