If getaddrinfo fails as soon as it fails forever (even after the network is ready)

I am writing a C application that starts as systemd service at boot (distro: Arch Linux) and which should connect to the server, since the application starts at boot, it ultimately happens that the network connection has not yet been established. This, of course, leads to the failure of the first function, which requires one, which in my case is getaddrinfo .

So, I thought that I would just write a loop that calls getaddrinfo repeatedly until it completes after the network is ready. Unfortunately, I found that getaddrinfo continues to work with name or service not known even after the connection is established.

I can ping the server by hostname, but getaddrinfo will not do this anyway. If I stop the application and start it again, everything will be fine. If the network connection is already established before the first call, getaddrinfo also works fine.

Apparently, if getaddrinfo failed once because the network was not ready, it would not be forever. He does not seem to know about the existing connection. When using an obsolete gethostbyname behavior will be the same.

What is the reason for this behavior? Is there a way to get getaddrinfo update internal variables (if any) or similar, which might explain why the function still thinks there is no connection? Is there another function that I would have to call earlier to check if the network is ready?

I would like to avoid the delay that waits for a while, waiting for the network to be connected afterwards. I would also prefer to test the connection from my application and not first run a bash script check and then run the application.

+5
source share
1 answer

You can understand the answer by compiling the following test program and following the instructions below:

 #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) { while (1) { struct addrinfo *res; int rc=getaddrinfo(argv[1], "http", NULL, &res); printf("getaddrinfo returned %d\n", rc); if (rc == 0) freeaddrinfo(res); sleep(1); } } 

Before running this test program:

  • Connection to a network.
  • Rename temporarily /etc/resolv.conf to /etc/resolv.conf.save .
  • Run this test program using a good hostname.
  • Soon after starting the test program and printing error codes, rename /etc/resolv.conf.save to /etc/resolv.conf .
  • Note that the test program is still reporting DNS resolution failures.
  • If you CTRL-C and restart it, the test program will now report a valid DNS resolution.

When disconnecting and reconnecting from the network, the network stack overwrites and updates /etc/resolv.conf respectively. This configuration file is required by the DNS resolver in library C. Library C first reads the DNS configuration from /etc/resolv.conf and caches it. It does not check on every search if the contents of /etc/resolv.conf has changed.

Finally:

  1. Your homework is to add the call to res_init() defined in resolv.h to this test program, read the corresponding manual page and see what happens. This is your answer.
+4
source

All Articles