From 20226b353004a566349dae8b1c5a4b1a403b5e72 Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Fri, 23 Jul 2004 15:29:53 +0000 Subject: [PATCH] Add a mutex to protect the per-process fake-getaddrinfo data cache. 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 | 8 ++++++++ src/include/fake-addrinfo.h | 28 ++++++++++++++++++++++++---- src/util/support/ChangeLog | 13 +++++++++++++ src/util/support/fake-addrinfo.c | 27 ++++++++++++++++++++++++++- src/util/support/threads.c | 29 ++++++++++++++++++++++------- 5 files changed, 93 insertions(+), 12 deletions(-) diff --git a/src/include/ChangeLog b/src/include/ChangeLog index 6bf9b88a6..103d4d7d7 100644 --- a/src/include/ChangeLog +++ b/src/include/ChangeLog @@ -1,3 +1,11 @@ +2004-07-23 Ken Raeburn + + * 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 * configure.in: Look for "struct lifconf" and maybe define diff --git a/src/include/fake-addrinfo.h b/src/include/fake-addrinfo.h index 09d2d6140..8b9639365 100644 --- a/src/include/fake-addrinfo.h +++ b/src/include/fake-addrinfo.h @@ -102,6 +102,7 @@ #include "port-sockets.h" #include "socket-utils.h" #include "k5-platform.h" +#include "k5-thread.h" #include /* 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 diff --git a/src/util/support/ChangeLog b/src/util/support/ChangeLog index 8a8034dfe..aff1b7aa9 100644 --- a/src/util/support/ChangeLog +++ b/src/util/support/ChangeLog @@ -1,3 +1,16 @@ +2004-07-23 Ken Raeburn + + * 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 * fake-addrinfo.c: New file. diff --git a/src/util/support/fake-addrinfo.c b/src/util/support/fake-addrinfo.c index 253763d19..233a29336 100644 --- a/src/util/support/fake-addrinfo.c +++ b/src/util/support/fake-addrinfo.c @@ -42,4 +42,29 @@ #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); +} diff --git a/src/util/support/threads.c b/src/util/support/threads.c index b6741c023..1e2430b9a 100644 --- a/src/util/support/threads.c +++ b/src/util/support/threads.c @@ -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(); } -- 2.26.2