Martin Husemann
2013-11-01 09:06:48 UTC
Hey folks,
assume you have a multi threaded, long running application. The app
does regular DNS queries using the high level APIs (getaddrinfo(3) and
friends) and uses a pool of threads specifically for those lookups.
Every now and then it wants to make sure that /etc/resolv.conf changes get
noticed and used by the resolver.
On FreeBSD and Linux each thread has a local _res variable, so the app
simply does:
res_ninit(&_res);
Scream, tear, feather! This is mixing the ancient (_res) API with the new
thread safe low level resolver API. But it is simple and works. Especially
given that there are NO other calls to the low level API.
Now on NetBSD this gets tricky. We cause an assertion failure when _res is
accessed from threaded programs.
The way to fix this with existing means seems to be: make the timeout
variable global and whenever one resolve threads hits the timeout, make
it reset the global variable atomically and then simply do:
res_init();
Now looking back at the whole picture, it seems that this all should
not be necessary at all. IMHO the resolver library should deal with it
internally, have a (application settable) timeout and after the timeout
expired stat /etc/resolv.conf on next access - and internally deal.
An alternative would be to have a full set of getaddrinfo_r(3),
getnameinfo_r(3), gethostbyaddr_r(3), gethostbyname_r(3), which get
passed a res_state*, so the resolver threads could just use a local
res_state and do res_init() on that whenever they like.
Did I overlook other options? Is there any precedence for the internal
solution (automatic res_ninit on changes of /etc/resolv.conf) in other
systems? Comments?
Thanks,
Martin
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
assume you have a multi threaded, long running application. The app
does regular DNS queries using the high level APIs (getaddrinfo(3) and
friends) and uses a pool of threads specifically for those lookups.
Every now and then it wants to make sure that /etc/resolv.conf changes get
noticed and used by the resolver.
On FreeBSD and Linux each thread has a local _res variable, so the app
simply does:
res_ninit(&_res);
Scream, tear, feather! This is mixing the ancient (_res) API with the new
thread safe low level resolver API. But it is simple and works. Especially
given that there are NO other calls to the low level API.
Now on NetBSD this gets tricky. We cause an assertion failure when _res is
accessed from threaded programs.
The way to fix this with existing means seems to be: make the timeout
variable global and whenever one resolve threads hits the timeout, make
it reset the global variable atomically and then simply do:
res_init();
Now looking back at the whole picture, it seems that this all should
not be necessary at all. IMHO the resolver library should deal with it
internally, have a (application settable) timeout and after the timeout
expired stat /etc/resolv.conf on next access - and internally deal.
An alternative would be to have a full set of getaddrinfo_r(3),
getnameinfo_r(3), gethostbyaddr_r(3), gethostbyname_r(3), which get
passed a res_state*, so the resolver threads could just use a local
res_state and do res_init() on that whenever they like.
Did I overlook other options? Is there any precedence for the internal
solution (automatic res_ninit on changes of /etc/resolv.conf) in other
systems? Comments?
Thanks,
Martin
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de