From owner-freebsd-arch@freebsd.org Wed Oct 7 21:56:02 2015 Return-Path: Delivered-To: freebsd-arch@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 940399D17FB for ; Wed, 7 Oct 2015 21:56:02 +0000 (UTC) (envelope-from jilles@stack.nl) Received: from mx1.stack.nl (relay04.stack.nl [IPv6:2001:610:1108:5010::107]) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (Client CN "mailhost.stack.nl", Issuer "CA Cert Signing Authority" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 5D7D8E9E; Wed, 7 Oct 2015 21:56:02 +0000 (UTC) (envelope-from jilles@stack.nl) Received: from snail.stack.nl (snail.stack.nl [IPv6:2001:610:1108:5010::131]) by mx1.stack.nl (Postfix) with ESMTP id 0499DB8098; Wed, 7 Oct 2015 23:55:59 +0200 (CEST) Received: by snail.stack.nl (Postfix, from userid 1677) id DE50928494; Wed, 7 Oct 2015 23:55:58 +0200 (CEST) Date: Wed, 7 Oct 2015 23:55:58 +0200 From: Jilles Tjoelker To: Eric van Gyzen Cc: freebsd-arch@freebsd.org Subject: Re: RFC: Automatically Reloading /etc/resolv.conf Message-ID: <20151007215558.GA41787@stack.nl> References: <5615886F.3060601@FreeBSD.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <5615886F.3060601@FreeBSD.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 07 Oct 2015 21:56:02 -0000 On Wed, Oct 07, 2015 at 04:02:39PM -0500, Eric van Gyzen wrote: > I would like to change the libc resolver to automatically reload > /etc/resolv.conf when the latter changes. I would like to hear opinions > about the implementation. Broadly, I see two approaches. > == "stat" == > When loading the file, record the mod time. Before each query, stat() > the file to see if it has changed. > Advantage: It uses no extra persistently allocated objects. > Disadvantage: It incurs a stat() on every query. I don't see this as a > major disadvantage, since the resolver already does a lot of work on > every query. (For example, it creates and destroys a kqueue and a socket.) > OpenBSD uses this approach. It also uses clock_gettime(CLOCK_MONOTONIC) > to rate-limit the stat() calls to one per several seconds. This looks reasonable. Nitpick: the resolver has used poll instead of kqueue for a while, but that does not fundamentally change your argument. Some glibc people think the extra stat may be too slow, though: https://sourceware.org/bugzilla/show_bug.cgi?id=984 > == "kqueue" == > When loading the file, open a kqueue and register for the appropriate > events. Before each query, check for kevents. > Advantage: The per-query overhead is fairly small. > Disadvantage: This would persistently allocate an open file and a > kqueue for every thread that ever uses the resolver, for the life of the > thread. This seems fairly expensive. This sounds a bit scary in conjunction with code that bluntly closes file descriptors it does not know about. Also, kqueues do not inherit across fork, so the resolver needs some sort of atfork handler. > NetBSD uses this approach. It mitigates most of the space-cost by using > a shared pool of res_state objects, instead of one per thread [that uses > the resolver]. On each query, a thread allocates/borrows a res_state > from the pool, uses it, and returns it. So, the number of objects is > only the high water mark of the number of threads _concurrently_ issuing > resolver queries. Is there code that depends on implicit per-thread res_state objects? If so, this will break it. > There are probably several variations on each theme, of course. I would > appreciate your thoughts on these approaches and others I missed, as > well as variations and details. > FYI, I'm leaning toward the "stat" approach. This seems safe, and being able to rely on automatic /etc/resolv.conf reloading can simplify application code considerably. The NextBSD people have a more efficient alternative notify(3). Using that, resolvconf(8) can cause a counter in shared memory to be incremented, which can be detected efficiently by the resolver in each process. The stat() approach need not wait for this, though. -- Jilles Tjoelker