Skip to content

Commit e40548b

Browse files
committed
Auto merge of #56779 - adrian-budau:master, r=alexcrichton
On musl targets assume certain symbols exist (like pipe2 and accept4). This fixes #56675. I don't know if this is the best solution, or if I should also add some tests so I'm waiting for some feedback. Thanks!
2 parents 01c6ea2 + bf172c5 commit e40548b

File tree

5 files changed

+78
-28
lines changed

5 files changed

+78
-28
lines changed

src/libstd/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@
250250
#![feature(cfg_target_vendor)]
251251
#![feature(char_error_internals)]
252252
#![feature(compiler_builtins_lib)]
253+
#![feature(concat_idents)]
253254
#![feature(const_int_ops)]
254255
#![feature(const_ip)]
255256
#![feature(const_raw_ptr_deref)]

src/libstd/sys/unix/net.rs

+14-11
Original file line numberDiff line numberDiff line change
@@ -203,18 +203,21 @@ impl Socket {
203203
// Linux. This was added in 2.6.28, however, and because we support
204204
// 2.6.18 we must detect this support dynamically.
205205
if cfg!(target_os = "linux") {
206-
weak! {
207-
fn accept4(c_int, *mut sockaddr, *mut socklen_t, c_int) -> c_int
206+
syscall! {
207+
fn accept4(
208+
fd: c_int,
209+
addr: *mut sockaddr,
210+
addr_len: *mut socklen_t,
211+
flags: c_int
212+
) -> c_int
208213
}
209-
if let Some(accept) = accept4.get() {
210-
let res = cvt_r(|| unsafe {
211-
accept(self.0.raw(), storage, len, SOCK_CLOEXEC)
212-
});
213-
match res {
214-
Ok(fd) => return Ok(Socket(FileDesc::new(fd))),
215-
Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {}
216-
Err(e) => return Err(e),
217-
}
214+
let res = cvt_r(|| unsafe {
215+
accept4(self.0.raw(), storage, len, SOCK_CLOEXEC)
216+
});
217+
match res {
218+
Ok(fd) => return Ok(Socket(FileDesc::new(fd))),
219+
Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {}
220+
Err(e) => return Err(e),
218221
}
219222
}
220223

src/libstd/sys/unix/os.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ pub fn errno() -> i32 {
6767
}
6868

6969
/// Sets the platform-specific value of errno
70-
#[cfg(any(target_os = "solaris", target_os = "fuchsia"))] // only needed for readdir so far
70+
#[cfg(all(not(target_os = "linux"),
71+
not(target_os = "dragonfly")))] // needed for readdir and syscall!
7172
pub fn set_errno(e: i32) {
7273
unsafe {
7374
*errno_location() = e as c_int
@@ -84,6 +85,18 @@ pub fn errno() -> i32 {
8485
unsafe { errno as i32 }
8586
}
8687

88+
#[cfg(target_os = "dragonfly")]
89+
pub fn set_errno(e: i32) {
90+
extern {
91+
#[thread_local]
92+
static mut errno: c_int;
93+
}
94+
95+
unsafe {
96+
errno = e;
97+
}
98+
}
99+
87100
/// Gets a detailed string description for the given error number.
88101
pub fn error_string(errno: i32) -> String {
89102
extern {

src/libstd/sys/unix/pipe.rs

+14-16
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use sys::{cvt, cvt_r};
2222
pub struct AnonPipe(FileDesc);
2323

2424
pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
25-
weak! { fn pipe2(*mut c_int, c_int) -> c_int }
25+
syscall! { fn pipe2(fds: *mut c_int, flags: c_int) -> c_int }
2626
static INVALID: AtomicBool = ATOMIC_BOOL_INIT;
2727

2828
let mut fds = [0; 2];
@@ -39,22 +39,20 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
3939
!INVALID.load(Ordering::SeqCst)
4040
{
4141

42-
if let Some(pipe) = pipe2.get() {
43-
// Note that despite calling a glibc function here we may still
44-
// get ENOSYS. Glibc has `pipe2` since 2.9 and doesn't try to
45-
// emulate on older kernels, so if you happen to be running on
46-
// an older kernel you may see `pipe2` as a symbol but still not
47-
// see the syscall.
48-
match cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) {
49-
Ok(_) => {
50-
return Ok((AnonPipe(FileDesc::new(fds[0])),
51-
AnonPipe(FileDesc::new(fds[1]))));
52-
}
53-
Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {
54-
INVALID.store(true, Ordering::SeqCst);
55-
}
56-
Err(e) => return Err(e),
42+
// Note that despite calling a glibc function here we may still
43+
// get ENOSYS. Glibc has `pipe2` since 2.9 and doesn't try to
44+
// emulate on older kernels, so if you happen to be running on
45+
// an older kernel you may see `pipe2` as a symbol but still not
46+
// see the syscall.
47+
match cvt(unsafe { pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC) }) {
48+
Ok(_) => {
49+
return Ok((AnonPipe(FileDesc::new(fds[0])),
50+
AnonPipe(FileDesc::new(fds[1]))));
51+
}
52+
Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {
53+
INVALID.store(true, Ordering::SeqCst);
5754
}
55+
Err(e) => return Err(e),
5856
}
5957
}
6058
cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;

src/libstd/sys/unix/weak.rs

+35
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,38 @@ unsafe fn fetch(name: &str) -> usize {
7777
};
7878
libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize
7979
}
80+
81+
#[cfg(not(target_os = "linux"))]
82+
macro_rules! syscall {
83+
(fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
84+
unsafe fn $name($($arg_name: $t),*) -> $ret {
85+
use libc;
86+
use super::os;
87+
88+
weak! { fn $name($($t),*) -> $ret }
89+
90+
if let Some(fun) = $name.get() {
91+
fun($($arg_name),*)
92+
} else {
93+
os::set_errno(libc::ENOSYS);
94+
-1
95+
}
96+
}
97+
)
98+
}
99+
100+
#[cfg(target_os = "linux")]
101+
macro_rules! syscall {
102+
(fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
103+
unsafe fn $name($($arg_name:$t),*) -> $ret {
104+
// This looks like a hack, but concat_idents only accepts idents
105+
// (not paths).
106+
use libc::*;
107+
108+
syscall(
109+
concat_idents!(SYS_, $name),
110+
$($arg_name as c_long),*
111+
) as $ret
112+
}
113+
)
114+
}

0 commit comments

Comments
 (0)