>From a0adc14afd6451d36143dae10454cb96870ee1b3 Mon Sep 17 00:00:00 2001 From: Matthew Newton Date: Sat, 17 Jan 2015 01:31:13 +0000 Subject: [PATCH 3/3] Add thread support to wb_common.c The global struct is converted to use pthread local storage if pthreads is available; otherwise fall back to using the global variable as before (which is safe as there are no threads). --- nsswitch/wb_common.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/nsswitch/wb_common.c b/nsswitch/wb_common.c index 5e499d5..eaa76d9 100644 --- a/nsswitch/wb_common.c +++ b/nsswitch/wb_common.c @@ -26,7 +26,68 @@ #include "system/select.h" #include "winbind_client.h" -/* Global variables. These are effectively the client state information */ +/* + Client state - how this is stored depends on whether pthreads is + available. When multithreaded, these values should not be shared + amongst different threads. +*/ + +#ifdef HAVE_PTHREAD + +#include + +static pthread_once_t thread_storage_once = PTHREAD_ONCE_INIT; +static pthread_key_t winbindd_fd_info_key; + +static void winbindd_fd_info_destructor(void *ptr) +{ + struct fd_info_s *fd_info = ptr; + + if (fd_info != NULL) { + if (fd_info->winbindd_fd != -1) { + close(fd_info->winbindd_fd); + } + + free(fd_info); + } + + pthread_setspecific(winbindd_fd_info_key, NULL); +} + +static void init_thread_storage(void) +{ + pthread_key_create(&winbindd_fd_info_key, winbindd_fd_info_destructor); +} + +/* Return pointer to file descriptor info from thread local storage */ + +struct fd_info_s *winbindd_fd_info(void) +{ + struct fd_info_s *fd_info; + + pthread_once(&thread_storage_once, init_thread_storage); + + fd_info = pthread_getspecific(winbindd_fd_info_key); + + if (fd_info == NULL) { + fd_info = malloc(sizeof(struct fd_info_s)); + + if (fd_info == NULL) { + return NULL; + } + + pthread_setspecific(winbindd_fd_info_key, fd_info); + + fd_info->winbindd_fd = -1; + fd_info->is_privileged = 0; + } + + return fd_info; +} + +#else + +/* If compiled without pthread support then use global variables. */ struct fd_info_s fd_info_global = { .winbindd_fd = -1, .is_privileged = 0 }; @@ -37,6 +98,8 @@ struct fd_info_s *winbindd_fd_info(void) return &fd_info_global; } +#endif + /* Free a response structure */ @@ -72,8 +135,10 @@ static void init_response(struct winbindd_response *response) /* Close established socket */ #if HAVE_FUNCTION_ATTRIBUTE_DESTRUCTOR +#ifndef HAVE_PTHREAD __attribute__((destructor)) #endif +#endif static void winbind_close_sock(void) { struct fd_info_s *fd_info; -- 1.7.10.4