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

Re: [patches] [PATCH] Reload resolv.conf for all threads



On Thu, Sep 16, 2010 at 08:05:33PM +0400, Maxim Kuvyrkov wrote:
> On 9/15/10 4:11 AM, Aurelien Jarno wrote:
> >When resolv.conf is modified, the resolver code noticed that and reload
> >it. However on a multithread program, the thread which notices the
> >change doesn't ask all the other to re-initialize their resolver. The
> >patch below fixes the issue.
> >
> >I submit it here, as this part of the code is EGLIBC specific and not p
> >art of GLIBC (though present in most distributions).
> 
> Michael (CC'ed) is the author of the code in question.

(Uh, that was a long time ago.) I think your patch is correct.
It's similar to a different patch from Sebastian Kienzl
<seb@xxxxxxxx>, which we currently use in our glibc:

diff -ur resolv.orig/res_libc.c resolv/res_libc.c
--- resolv.orig/res_libc.c	2005-11-01 01:06:40.000000000 +0100
+++ resolv/res_libc.c	2010-03-15 14:13:18.000000000 +0100
@@ -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
@@ -89,12 +89,34 @@
 	return (__res_vinit(&_res, 1));
 }
 
+static time_t resconf_mtime;
+__libc_lock_define_initialized (static, resconf_mtime_lock);
+
+/* Check if the modification time of resolv.conf has changed.
+   If so, have all threads re-initialize their resolver states */
+static void
+__res_check_resconf (void)
+{
+	struct stat statbuf;
+	if (stat (_PATH_RESCONF, &statbuf) == 0) {
+		__libc_lock_lock (resconf_mtime_lock);
+		if (statbuf.st_mtime != resconf_mtime) {
+			resconf_mtime = statbuf.st_mtime;
+			atomicinclock (lock);
+			atomicinc (__res_initstamp);
+			atomicincunlock (lock);
+		}
+		__libc_lock_unlock (resconf_mtime_lock);
+	}
+}
+
 /* Initialize resp if RES_INIT is not yet set or if res_init in some other
    thread requested re-initializing.  */
 int
 __res_maybe_init (res_state resp, int preinit)
 {
 	if (resp->options & RES_INIT) {
+		__res_check_resconf ();
 		if (__res_initstamp != resp->_u._ext.initstamp) {
 			if (resp->nscount > 0)
 				__res_iclose (resp, true);



Cheers,
  Michael.

-- 
Michael Schroeder                                   mls@xxxxxxx
SUSE LINUX Products GmbH, GF Markus Rex, HRB 16746 AG Nuernberg
main(_){while(_=~getchar())putchar(~_-1/(~(_|32)/13*2-11)*13);}