diff options
author | green <green@FreeBSD.org> | 2004-02-25 21:03:46 +0000 |
---|---|---|
committer | green <green@FreeBSD.org> | 2004-02-25 21:03:46 +0000 |
commit | 40452493ee2a89d18609e7a71f114981ff6a315a (patch) | |
tree | 9638e0bc7f96f243bb180d862cc5f1093a53454c /lib/libc/net/getaddrinfo.c | |
parent | 821b77eba39a417a7e8283015b0d7dcf52875715 (diff) | |
download | FreeBSD-src-40452493ee2a89d18609e7a71f114981ff6a315a.zip FreeBSD-src-40452493ee2a89d18609e7a71f114981ff6a315a.tar.gz |
Make the resolver(3) and many associated interfaces much more reentrant.
The getaddrinfo(3), getipnodebyname(3) and resolver(3) can coincide now
with what should be totally reentrant, and h_errno values will now
be preserved correctly, but this does not affect interfaces such as
gethostbyname(3) which are still mostly non-reentrant.
In all of these relevant functions, the thread-safety has been pushed
down as far as it seems possible right now. This means that operations
that are selected via nsdispatch(3) (i.e. files, yp, dns) are protected
still under global locks that getaddrinfo(3) defines, but where possible
the locking is greatly reduced. The most noticeable improvement is
that multiple DNS lookups can now be run at the same time, and this
shows major improvement in performance of DNS-lookup threaded programs,
and solves the "Mozilla tab serialization" problem.
No single-threaded applications need to be recompiled. Multi-threaded
applications that reference "_res" to change resolver(3) options will
need to be recompiled, and ones which reference "h_errno" will also
if they desire the correct h_errno values. If the applications already
understood that _res and h_errno were not thread-safe and had their own
locking, they will see no performance improvement but will not
actually break in any way.
Please note that when NSS modules are used, or when nsdispatch(3)
defaults to adding any lookups of its own to the individual libc
_nsdispatch() calls, those MUST be reentrant as well.
Diffstat (limited to 'lib/libc/net/getaddrinfo.c')
-rw-r--r-- | lib/libc/net/getaddrinfo.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c index df05b0e..dc21cc2 100644 --- a/lib/libc/net/getaddrinfo.c +++ b/lib/libc/net/getaddrinfo.c @@ -305,10 +305,10 @@ static struct ai_errlist { }; /* - * XXX: Our res_*() is not thread-safe. So, we share lock between + * XXX: Many dependencies are not thread-safe. So, we share lock between * getaddrinfo() and getipnodeby*(). Still, we cannot use * getaddrinfo() and getipnodeby*() in conjunction with other - * functions which call res_*(). + * functions which call them. */ pthread_mutex_t __getaddrinfo_thread_lock = PTHREAD_MUTEX_INITIALIZER; #define THREAD_LOCK() \ @@ -1348,9 +1348,13 @@ get_port(ai, servname, matchonly) break; } - if ((sp = getservbyname(servname, proto)) == NULL) + THREAD_LOCK(); + if ((sp = getservbyname(servname, proto)) == NULL) { + THREAD_UNLOCK(); return EAI_SERVICE; + } port = sp->s_port; + THREAD_UNLOCK(); } if (!matchonly) { @@ -1501,15 +1505,11 @@ explore_fqdn(pai, hostname, servname, res) result = NULL; - THREAD_LOCK(); - /* * if the servname does not match socktype/protocol, ignore it. */ - if (get_portmatch(pai, servname) != 0) { - THREAD_UNLOCK(); + if (get_portmatch(pai, servname) != 0) return 0; - } switch (_nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo", default_dns_files, hostname, pai)) { @@ -1530,14 +1530,12 @@ explore_fqdn(pai, hostname, servname, res) } break; } - THREAD_UNLOCK(); *res = result; return 0; free: - THREAD_UNLOCK(); if (result) freeaddrinfo(result); return error; @@ -2037,6 +2035,7 @@ _files_getaddrinfo(rv, cb_data, ap) memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; + THREAD_LOCK(); _sethtent(); while ((p = _gethtent(name, pai)) != NULL) { cur->ai_next = p; @@ -2044,6 +2043,7 @@ _files_getaddrinfo(rv, cb_data, ap) cur = cur->ai_next; } _endhtent(); + THREAD_UNLOCK(); *((struct addrinfo **)rv) = sentinel.ai_next; if (sentinel.ai_next == NULL) @@ -2152,9 +2152,12 @@ _yp_getaddrinfo(rv, cb_data, ap) memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; + THREAD_LOCK(); if (!__ypdomain) { - if (_yp_check(&__ypdomain) == 0) + if (_yp_check(&__ypdomain) == 0) { + THREAD_UNLOCK(); return NS_UNAVAIL; + } } if (__ypcurrent) free(__ypcurrent); @@ -2189,6 +2192,7 @@ _yp_getaddrinfo(rv, cb_data, ap) cur = cur->ai_next; } } + THREAD_UNLOCK(); if (sentinel.ai_next == NULL) { h_errno = HOST_NOT_FOUND; @@ -2202,7 +2206,6 @@ _yp_getaddrinfo(rv, cb_data, ap) /* resolver logic */ extern const char *__hostalias(const char *); -extern int h_errno; /* * Formulate a normal query, send, and await answer. |