Skip to content

Commit c976be5

Browse files
committed
Implement improved feature detection on Linux
1 parent 3ecbe33 commit c976be5

File tree

2 files changed

+89
-4
lines changed

2 files changed

+89
-4
lines changed

src/features.rs

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,99 @@ pub use self::os::*;
22

33
#[cfg(target_os = "linux")]
44
mod os {
5-
pub fn atomic_cloexec() -> bool {
6-
true // TODO: Not on all kernel versions
5+
use sys::utsname::uname;
6+
7+
// Features:
8+
// * atomic cloexec on socket: 2.6.27
9+
// * pipe2: 2.6.27
10+
// * accept4: 2.6.28
11+
12+
static VERS_UNKNOWN: uint = 1;
13+
static VERS_2_6_18: uint = 2;
14+
static VERS_2_6_27: uint = 3;
15+
static VERS_2_6_28: uint = 4;
16+
static VERS_3: uint = 5;
17+
18+
fn parse_kernel_version() -> uint {
19+
let u = uname();
20+
21+
#[inline]
22+
fn digit(dst: &mut uint, b: u8) {
23+
*dst *= 10;
24+
*dst += (b - b'0') as uint;
25+
}
26+
27+
let mut curr = 0u;
28+
let mut major = 0;
29+
let mut minor = 0;
30+
let mut patch = 0;
31+
32+
for b in u.release().bytes() {
33+
if curr >= 3 {
34+
break;
35+
}
36+
37+
match b {
38+
b'.' | b'-' => {
39+
curr += 1;
40+
}
41+
b'0'...b'9' => {
42+
match curr {
43+
0 => digit(&mut major, b),
44+
1 => digit(&mut minor, b),
45+
_ => digit(&mut patch, b),
46+
}
47+
}
48+
_ => break,
49+
}
50+
}
51+
52+
if major >= 3 {
53+
VERS_3
54+
} else if major >= 2 {
55+
if minor >= 7 {
56+
VERS_UNKNOWN
57+
} else if minor >= 6 {
58+
if patch >= 28 {
59+
VERS_2_6_28
60+
} else if patch >= 27 {
61+
VERS_2_6_27
62+
} else {
63+
VERS_2_6_18
64+
}
65+
} else {
66+
VERS_UNKNOWN
67+
}
68+
} else {
69+
VERS_UNKNOWN
70+
}
71+
}
72+
73+
fn kernel_version() -> uint {
74+
static mut KERNEL_VERS: uint = 0;
75+
76+
unsafe {
77+
if KERNEL_VERS == 0 {
78+
KERNEL_VERS = parse_kernel_version();
79+
}
80+
81+
KERNEL_VERS
82+
}
83+
}
84+
85+
pub fn socket_atomic_cloexec() -> bool {
86+
kernel_version() >= VERS_2_6_27
87+
}
88+
89+
#[test]
90+
pub fn test_parsing_kernel_version() {
91+
assert!(kernel_version() > 0);
792
}
893
}
994

1095
#[cfg(any(target_os = "macos", target_os = "ios"))]
1196
mod os {
12-
pub fn atomic_cloexec() -> bool {
97+
pub fn socket_atomic_cloexec() -> bool {
1398
false
1499
}
15100
}

src/sys/socket.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ mod consts {
162162
}
163163

164164
pub fn socket(domain: AddressFamily, mut ty: SockType, flags: SockFlag) -> SysResult<Fd> {
165-
let feat_atomic = features::atomic_cloexec();
165+
let feat_atomic = features::socket_atomic_cloexec();
166166

167167
if feat_atomic {
168168
ty = ty | flags.bits();

0 commit comments

Comments
 (0)