I am writing a C application which is run as a systemd service on boot (distro: Arch Linux) and which shall connect to a server. Because the application is run on boot it eventually happens that the network connection is not yet established. This naturally leads to a failure of the first function which requires one, which in my case is getaddrinfo
.
So I thought that I would just write a loop which repeatedly calls getaddrinfo
until it suceeds once the network is ready. Unfortunately I found that getaddrinfo
keeps failing with name or service not known
even after the connection was established.
I am able to ping the server by its hostname but getaddrinfo
still won't do it. If I stop the application and run it again, everything works fine. If the network connection is already established before the first call, getaddrinfo
works fine too.
Apparently, if getaddrinfo
failed once because the network was not ready, it will fail forever. It seems not to be aware of the now existing connection. When using the deprecated gethostbyname
, the behaviour is the same.
What is the reason for this behaviour? Is there a way to force getaddrinfo
to refresh internal variables (if such exist) or similar which might explain why the function still believes that there is no connection? Is there another function which I should call previously in order to check whether the network is ready?
I would like to avoid a delay which waits for some time, expecting the network to be connected afterwards. I would also prefer to check for a connection from within my application and not have a bash script first check for it and then start the application.
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 you run this test program:
/etc/resolv.conf
to /etc/resolv.conf.save
./etc/resolv.conf.save
to /etc/resolv.conf
.When you disconnect and reconnect from the network, your network stack rewrites and updates /etc/resolv.conf
accordingly. This configuration file is needed by the DNS resolver in the C library. The C library reads the DNS configuration from /etc/resolv.conf
the first time, and caches it. It doesn't check, with every lookup, if the contents of /etc/resolv.conf
have changed.
Finally:
res_init()
, defined in resolv.h
, to this test program, read the corresponding man page, and see what happens. That's your answer.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With