if err == 0 {
return Ok(())
}
+
+ // We may need to trigger a glibc workaround. See on_resolver_failure() for details.
+ on_resolver_failure();
+
if err == EAI_SYSTEM {
return Err(io::Error::last_os_error())
}
// res_init unconditionally, we call it only when we detect we're linking
// against glibc version < 2.26. (That is, when we both know its needed and
// believe it's thread-safe).
-pub fn res_init_if_glibc_before_2_26() -> io::Result<()> {
+#[cfg(target_env = "gnu")]
+fn on_resolver_failure() {
// If the version fails to parse, we treat it the same as "not glibc".
if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) {
if let Some(version) = parse_glibc_version(version_str) {
if version < (2, 26) {
- let ret = unsafe { libc::res_init() };
- if ret != 0 {
- return Err(io::Error::last_os_error());
- }
+ unsafe { libc::res_init() };
}
}
}
- Ok(())
}
+#[cfg(not(target_env = "gnu"))]
+fn on_resolver_failure() {}
+
+#[cfg(target_env = "gnu")]
fn glibc_version_cstr() -> Option<&'static CStr> {
weak! {
fn gnu_get_libc_version() -> *const libc::c_char
// Returns Some((major, minor)) if the string is a valid "x.y" version,
// ignoring any extra dot-separated parts. Otherwise return None.
+#[cfg(target_env = "gnu")]
fn parse_glibc_version(version: &str) -> Option<(usize, usize)> {
let mut parsed_ints = version.split(".").map(str::parse::<usize>).fuse();
match (parsed_ints.next(), parsed_ints.next()) {
}
}
-#[cfg(test)]
+#[cfg(all(test, taget_env = "gnu"))]
mod test {
use super::*;
hints.ai_socktype = c::SOCK_STREAM;
let mut res = ptr::null_mut();
unsafe {
- match cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res)) {
- Ok(_) => {
- Ok(LookupHost { original: res, cur: res })
- },
- #[cfg(unix)]
- Err(e) => {
- // If we're running glibc prior to version 2.26, the lookup
- // failure could be caused by caching a stale /etc/resolv.conf.
- // We need to call libc::res_init() to clear the cache. But we
- // shouldn't call it in on any other platform, because other
- // res_init implementations aren't thread-safe. See
- // https://github.com/rust-lang/rust/issues/41570 and
- // https://github.com/rust-lang/rust/issues/43592.
- use sys::net::res_init_if_glibc_before_2_26;
- let _ = res_init_if_glibc_before_2_26();
- Err(e)
- },
- // the cfg is needed here to avoid an "unreachable pattern" warning
- #[cfg(not(unix))]
- Err(e) => Err(e),
- }
+ cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res)).map(|_| {
+ LookupHost { original: res, cur: res }
+ })
}
}