>From 920ef9c1cf0b0ba29dbfc13a59f13a419ba15a09 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 | 62 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/nsswitch/wb_common.c b/nsswitch/wb_common.c index 359a72c..e8aa98b 100644 --- a/nsswitch/wb_common.c +++ b/nsswitch/wb_common.c @@ -26,7 +26,63 @@ #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); + + if ((fd_info = pthread_getspecific(winbindd_fd_info_key)) == 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 +93,8 @@ struct fd_info_s *winbindd_fd_info(void) return &fd_info_global; } +#endif + /* Free a response structure */ @@ -72,8 +130,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