[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [patches] Track resolv.conf, avoid need for explicit res_init() or nscd in long-running applications



> Date: Mon, 12 Oct 2009 17:58:56 +0000 (UTC)
> From: "Joseph S. Myers" <joseph@xxxxxxxxxxxxxxxx>

> This diff does not apply cleanly to current sources.  Could you send a 
> version that does (and is tested still to have the desired effect)?

Oops, a line or two changed between 2.9 and trunk, I missed
that.  Sorry.

Updated patch follows, as harvested from Debian (still
misattributed there as Thorsten's, so I guess the authorship is
still with his colleague Michael Schroeder) and the previous
ChangeLog entry still applies.

I tested it with the following program pre/post the patch
applied to r9077 of eglibc trunk, built for
arm-axis-linux-gnueabi, changing to/from a bad /etc/resolv.conf
("nameserver" line pointing at the wrong host).  The intended
result, the output changing to/from "gethostbyname badness: Host
name lookup failure" to displaying the IP address happened after
the patch only.  NB: I'm probably not using the correct DNS
lookup idioms and sorry for using the obsolete gethostbyname. :)

BTW, something incompatibly happened between 2.9 and trunk
causing SEGV if I just point at libc.so.6 using LD_LIBRARY_PATH,
e.g.:
 env LD_LIBRARY_PATH=/tmp ./ghbn
I had to also use the newly compiled dynamic linker and (cd /tmp)
 ./ld-linux.so.3 --library-path /tmp ./ghbn

Index: res_libc.c
===================================================================
--- res_libc.c	(revision 9077)
+++ res_libc.c	(working copy)
@@ -22,7 +22,7 @@
 #include <arpa/nameser.h>
 #include <resolv.h>
 #include <bits/libc-lock.h>
-
+#include <sys/stat.h>
 
 /* The following bit is copied from res_data.c (where it is #ifdef'ed
    out) since res_init() should go into libc.so but the rest of that
@@ -94,8 +94,15 @@ res_init(void) {
 int
 __res_maybe_init (res_state resp, int preinit)
 {
+	static time_t last_mtime;
+	struct stat statbuf;
+	int ret;
+
 	if (resp->options & RES_INIT) {
-		if (__res_initstamp != resp->_u._ext.initstamp) {
+		ret = stat (_PATH_RESCONF, &statbuf);
+		if ((__res_initstamp != resp->_u._ext.initstamp)
+		    || ((ret == 0) && (last_mtime != statbuf.st_mtime))) {
+			last_mtime = statbuf.st_mtime;
 			if (resp->nscount > 0)
 				__res_iclose (resp, true);
 			return __res_vinit (resp, 1);

ghbn.c:
#include <stdlib.h>
#include <stdio.h>
#include <netdb.h>
#define NAME1 "eglibc.org"
#define NAME2 "gnu.org"

int main (void)
{
  char digs[INET_ADDRSTRLEN];
  struct hostent *hep;

  hep = gethostbyname (NAME1);
  if (hep == NULL)
    fprintf (stderr, "gethostbyname badness: %s\n", hstrerror (h_errno));
  else
    {
      inet_ntop (hep->h_addrtype, hep->h_addr, digs, sizeof digs);
      printf ("%s is: %s\n", NAME1, digs);
    }

  printf ("Now do something to /etc/resolv.conf and press the \"any\" key\n");
  getchar();

  hep = gethostbyname (NAME2);
  if (hep == NULL)
    {
      fprintf (stderr, "gethostbyname badness: %s\n", hstrerror (h_errno));
      exit (1);
    }
  else
    {
      inet_ntop (hep->h_addrtype, hep->h_addr, digs, sizeof digs);
      printf ("%s is: %s\n", NAME2, digs);
    }

  exit (0);
}

brgds, H-P