Add a mutex to protect the per-process fake-getaddrinfo data cache.
authorKen Raeburn <raeburn@mit.edu>
Fri, 23 Jul 2004 15:29:53 +0000 (15:29 +0000)
committerKen Raeburn <raeburn@mit.edu>
Fri, 23 Jul 2004 15:29:53 +0000 (15:29 +0000)
Currently it gets locked while a name lookup is in progress, which is not very
efficient.  That should be changed, after the code is fixed up so that the
cache works on other platforms.

* include/fake-addrinfo.h: Include k5-thread.h.
(struct fac): Add a mutex.
(plant_face, find_face): Check that mutex is already locked.
(krb5int_lock_fac, krb5int_unlock_fac): Declare.
(fai_add_hosts_by_name): Use them to lock and unlock the mutex.
* util/support/fake-addrinfo.c (krb5int_fac): Initialize the mutex.
(krb5int_init_fac, krb5int_fini_fac): New functions; finish initializing or
destroy the mutex.
(krb5int_lock_fac, krb5int_unlock_fac): New functions; lock the mutex after
calling krb5int_call_thread_support_init, or unlock it.
* util/support/threads.c (krb5int_call_thread_support_init): New function.
(krb5int_init_fac, krb5int_fini_fac): Declare.
(krb5int_thread_support_init, krb5int_thread_support_fini): Call them.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@16622 dc483132-0cff-0310-8789-dd5450dbe970

src/include/ChangeLog
src/include/fake-addrinfo.h
src/util/support/ChangeLog
src/util/support/fake-addrinfo.c
src/util/support/threads.c

index 6bf9b88a69c0a56a98a8f0ec98a4612be5672b43..103d4d7d7e562a29f2201399b89e15dff852cdf2 100644 (file)
@@ -1,3 +1,11 @@
+2004-07-23  Ken Raeburn  <raeburn@mit.edu>
+
+       * fake-addrinfo.h: Include k5-thread.h.
+       (struct fac): Add a mutex.
+       (plant_face, find_face): Check that mutex is already locked.
+       (krb5int_lock_fac, krb5int_unlock_fac): Declare.
+       (fai_add_hosts_by_name): Use them to lock and unlock the mutex.
+
 2004-07-22  Ken Raeburn  <raeburn@mit.edu>
 
        * configure.in: Look for "struct lifconf" and maybe define
index 09d2d6140f3e36646a7077d7c6d1d60c49fd2fe1..8b9639365de72f3c4d92f375e88113fca0ef5f85 100644 (file)
 #include "port-sockets.h"
 #include "socket-utils.h"
 #include "k5-platform.h"
+#include "k5-thread.h"
 
 #include <stdio.h>             /* for sprintf */
 
@@ -580,6 +581,7 @@ struct face {
 
 /* fake addrinfo cache */
 struct fac {
+    k5_mutex_t lock;
     struct face *data;
 };
 extern struct fac krb5int_fac;
@@ -645,6 +647,7 @@ static void plant_face (const char *name, struct face *entry)
     if (entry->name == NULL)
        /* @@ Wastes memory.  */
        return;
+    k5_mutex_assert_locked(&krb5int_fac.lock);
     entry->next = krb5int_fac.data;
     entry->expiration = time(0) + CACHE_ENTRY_LIFETIME;
     krb5int_fac.data = entry;
@@ -664,6 +667,7 @@ static int find_face (const char *name, struct face **entry)
 #ifdef DEBUG_ADDRINFO
     printf("scanning cache at %d for '%s'...\n", now, name);
 #endif
+    k5_mutex_assert_locked(&krb5int_fac.lock);
     for (fpp = &krb5int_fac.data; *fpp; ) {
        fp = *fpp;
 #ifdef DEBUG_ADDRINFO
@@ -703,6 +707,8 @@ static int find_face (const char *name, struct face **entry)
 
 #endif
 
+extern int krb5int_lock_fac(void), krb5int_unlock_fac(void);
+
 static inline int fai_add_hosts_by_name (const char *name,
                                         struct addrinfo *template,
                                         int portnum, int flags,
@@ -711,8 +717,13 @@ static inline int fai_add_hosts_by_name (const char *name,
 #ifdef FAI_CACHE
 
     struct face *ce;
-    int i, r;
+    int i, r, err;
 
+    err = krb5int_lock_fac();
+    if (err) {
+       errno = err;
+       return EAI_SYSTEM;
+    }
     if (!find_face(name, &ce)) {
        struct addrinfo myhints = { 0 }, *ai, *ai2;
        int i4, i6, aierr;
@@ -729,8 +740,10 @@ static inline int fai_add_hosts_by_name (const char *name,
           asked for IPv4 only, but let's deal with that later, if we
           have to.  */
        aierr = system_getaddrinfo(name, "telnet", &myhints, &ai);
-       if (aierr)
+       if (aierr) {
+           krb5int_unlock_fac();
            return aierr;
+       }
        ce = malloc(sizeof(struct face));
        memset(ce, 0, sizeof(*ce));
        ce->expiration = time(0) + 30;
@@ -751,11 +764,13 @@ static inline int fai_add_hosts_by_name (const char *name,
        }
        ce->addrs4 = calloc(ce->naddrs4, sizeof(*ce->addrs4));
        if (ce->addrs4 == NULL && ce->naddrs4 != 0) {
+           krb5int_unlock_fac();
            system_freeaddrinfo(ai);
            return EAI_MEMORY;
        }
        ce->addrs6 = calloc(ce->naddrs6, sizeof(*ce->addrs6));
        if (ce->addrs6 == NULL && ce->naddrs6 != 0) {
+           krb5int_unlock_fac();
            free(ce->addrs4);
            system_freeaddrinfo(ai);
            return EAI_MEMORY;
@@ -780,18 +795,23 @@ static inline int fai_add_hosts_by_name (const char *name,
     template->ai_addrlen = sizeof(struct sockaddr_in6);
     for (i = 0; i < ce->naddrs6; i++) {
        r = fai_add_entry (result, &ce->addrs6[i], portnum, template);
-       if (r)
+       if (r) {
+           krb5int_unlock_fac();
            return r;
+       }
     }
     template->ai_family = AF_INET;
     template->ai_addrlen = sizeof(struct sockaddr_in);
     for (i = 0; i < ce->naddrs4; i++) {
        r = fai_add_entry (result, &ce->addrs4[i], portnum, template);
-       if (r)
+       if (r) {
+           krb5int_unlock_fac();
            return r;
+       }
     }
     if (*result && (flags & AI_CANONNAME))
        (*result)->ai_canonname = strdup(ce->canonname);
+    krb5int_unlock_fac();
     return 0;
 
 #else
index 8a8034dfe5594df8fe52ea1887234a2046000677..aff1b7aa9e13fd141468f0ce8eee099a1262c7e3 100644 (file)
@@ -1,3 +1,16 @@
+2004-07-23  Ken Raeburn  <raeburn@mit.edu>
+
+       * fake-addrinfo.c (krb5int_fac): Initialize the mutex.
+       (krb5int_init_fac, krb5int_fini_fac): New functions; finish
+       initializing or destroy the mutex.
+       (krb5int_lock_fac, krb5int_unlock_fac): New functions; lock the
+       mutex after calling krb5int_call_thread_support_init, or unlock
+       it.
+       * threads.c (krb5int_call_thread_support_init): New function.
+       (krb5int_init_fac, krb5int_fini_fac): Declare.
+       (krb5int_thread_support_init, krb5int_thread_support_fini): Call
+       them.
+
 2004-07-19  Ken Raeburn  <raeburn@mit.edu>
 
        * fake-addrinfo.c: New file.
index 253763d19e694513e589256adaab35389b5fdaa2..233a2933664d9f506f0573a5cb677813af1cc651 100644 (file)
 #include "fake-addrinfo.h"
 
 /* Allocate the storage here.  */
-struct fac krb5int_fac = { 0 };
+struct fac krb5int_fac = { K5_MUTEX_PARTIAL_INITIALIZER, 0 };
+
+int krb5int_init_fac (void)
+{
+    return k5_mutex_finish_init(&krb5int_fac.lock);
+}
+
+void krb5int_fini_fac (void)
+{
+    k5_mutex_destroy(&krb5int_fac.lock);
+}
+
+extern int krb5int_call_thread_support_init(void);
+int krb5int_lock_fac (void)
+{
+    int err;
+    err = krb5int_call_thread_support_init();
+    if (err)
+       return err;
+    return k5_mutex_lock(&krb5int_fac.lock);
+}
+
+int krb5int_unlock_fac (void)
+{
+    return k5_mutex_unlock(&krb5int_fac.lock);
+}
index b6741c02360382872ae99a432d493b38a973d0d7..1e2430b9a50323a755c55c3d9c14a3550fd48bef 100644 (file)
@@ -317,43 +317,56 @@ int k5_key_delete (k5_key_t keynum)
     return 0;
 }
 
+int krb5int_call_thread_support_init (void)
+{
+    return CALL_INIT_FUNCTION(krb5int_thread_support_init);
+}
+
+extern int krb5int_init_fac(void);
+extern void krb5int_fini_fac(void);
+
 int krb5int_thread_support_init (void)
 {
+    int err;
+
 #ifndef ENABLE_THREADS
 
-    return 0;
+    /* Nothing to do for TLS initialization.  */
 
 #elif defined(_WIN32)
 
     tls_idx = TlsAlloc();
     /* XXX This can raise an exception if memory is low!  */
     InitializeCriticalSection(&key_lock);
-    return 0;
 
 #else /* POSIX */
 
-    int err;
     err = k5_mutex_finish_init(&key_lock);
     if (err)
        return err;
     if (K5_PTHREADS_LOADED)
        return pthread_key_create(&key, thread_termination);
-    else
-       return 0;
 
 #endif
+
+    err = krb5int_init_fac();
+    if (err)
+       return err;
+
+    return 0;
 }
 
 void krb5int_thread_support_fini (void)
 {
+    if (! INITIALIZER_RAN (krb5int_thread_support_init))
+       return;
+
 #ifndef ENABLE_THREADS
 
     /* Do nothing.  */
 
 #elif defined(_WIN32)
 
-    if (! INITIALIZER_RAN (krb5int_thread_support_init))
-       return;
     /* ... free stuff ... */
     TlsFree(tls_idx);
     DeleteCriticalSection(&key_lock);
@@ -368,5 +381,7 @@ void krb5int_thread_support_fini (void)
     k5_mutex_destroy(&key_lock);
 
 #endif
+
+    krb5int_fini_fac();
 }