Skip to content

No way to refresh DNS information leading to indefinite network failures #41570

Closed
@jonhoo

Description

@jonhoo

Consider the following simple network client:

fn main() {
    use std::thread;
    use std::time::Duration;
    use std::net::TcpStream;

    loop {
        match TcpStream::connect("google.com:80") {
            Ok(_) => {
                println!("connected");
                break;
            }
            Err(e) => {
                println!("failed: {:?}", e);
            }
        }
        thread::sleep(Duration::from_secs(1));
    }
}

This works fine if you run it while your internet connection is up and running. However, if you kill your network connection, it (obviously) does not. What is interesting is if you launch the program while your internet is offline (and crucially, while /etc/resolv.conf does not contain any nameservers), and then connect to the internet again. I would expect the program to eventually say "connected", however this is not the case.

This had me puzzle for a while, until I stumbled on this old issue on the Pidgin bug tracker. It turns out that the set of nameservers available when the program is started is cached, and is never automatically re-read. Instead, res_init must be called manually to refresh the nameserver list. Unfortunately, as far as I can tell, there is no way in Rust to call res_init, and thus the above program simply cannot be made to work in the presence of network failures.

It's not entirely clear what the "right" fix here is: we could simply providing a way to call res_init, or we could do something more fancy like a special connect_uncached that does it for you. Regardless, this seems like a fairly unfortunate shortcoming..

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions