This is the mail archive of the libc-help@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: getaddrinfo() fails to use latest DNS address - v2.27


* Tarun Tej K.:

> I have gone through glibc code and have a query regarding below part
> from the function maybe_init() in file resolv/resolv_context.c
>
> if (ctx->conf != NULL && replicated_configuration_matches (ctx))
>         {
>           struct resolv_conf *current = __resolv_conf_get_current ();
>           if (current == NULL)
>             return false;
>           /* Check if the configuration changed.  */
>           if (current != ctx->conf)
>             {
>               /* This call will detach the extended resolver state.  */
>               if (resp->nscount > 0)
>                 __res_iclose (resp, true);
>               /* Reattach the current configuration.  */
>               if (__resolv_conf_attach (ctx->resp, current))
>                 {
>                   __resolv_conf_put (ctx->conf);
>                   /* ctx takes ownership, so we do not release current.  */
>                   ctx->conf = current;
>                 }
>             }
>           else
>             /* No change.  Drop the reference count for current.  */
>             __resolv_conf_put (current);
>         }
>       return true;
>
> Here the return value will be 'true' even when the condition   if
> (ctx->conf != NULL && replicated_configuration_matches (ctx)) fails. I
> think that  this is one case where __resolv_conf_get_current() or
> __resolv_conf_load()  would not be  called and so 'stat64' or openat()
> would not be done on /etc/resolv.conf. Why is the function maybe_init
> returning 'true' when the condition (ctx->conf != NULL &&
> replicated_configuration_matches (ctx)) fails?

The expectation here is that __resolv_conf_load performed the stat64
call and reloaded the configuration if necessary.  maybe_init returns
false only in case of resource exhaustion (e.g., memory allocation
failure).

Doe this answer your question?  I'm afraid the bug must be elsewhere.

We use stat64 in __resolv_conf_get_current, so it should not matter
whether /etc/resolv.conf is a symbolic link or not.  I believe the
function deals correctly with missing files or symbolic links that
cannot be resolved.  It produces an invalid, all-zero stat result and
caches that.  If the file becomes available again, the cached contents
no longer matches, and a reload is triggered.

How do you replace /etc/resolv.conf?  If the file is overwritten
in-place and the file system does not have nanosecond resolution for its
timestamps, then glibc might read an empty (or partial) /etc/resolv.conf
file, but might not realize that the file changed again later because
the subsequent writes do modify the file timestamps (due to the
timestamp resolution).  The fix is to write the new version of
/etc/resolv.conf to a temporary file (in the same directory) and rename
it into place, atomically.

Thanks,
Florian


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]