From 86b61156743b7ebdc049450a6f88452890fd9a61 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Mon, 13 Aug 2012 15:30:39 +0200 Subject: Use PTHREAD_MUTEX_ROBUST to avoid deadlock in the client https://fedorahosted.org/sssd/ticket/1460 --- src/sss_client/common.c | 96 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 6 deletions(-) (limited to 'src/sss_client') diff --git a/src/sss_client/common.c b/src/sss_client/common.c index 59eae3b1f..5b1751593 100644 --- a/src/sss_client/common.c +++ b/src/sss_client/common.c @@ -976,24 +976,108 @@ errno_t sss_strnlen(const char *str, size_t maxlen, size_t *len) } #if HAVE_PTHREAD -static pthread_mutex_t sss_nss_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_mutex_t sss_pam_mutex = PTHREAD_MUTEX_INITIALIZER; +typedef void (*sss_mutex_init)(void); +struct sss_mutex { + pthread_mutex_t mtx; + + pthread_once_t once; + sss_mutex_init init; +}; + +static void sss_nss_mt_init(void); +static void sss_pam_mt_init(void); + +static struct sss_mutex sss_nss_mtx = { .mtx = PTHREAD_MUTEX_INITIALIZER, + .once = PTHREAD_ONCE_INIT, + .init = sss_nss_mt_init }; + +static struct sss_mutex sss_pam_mtx = { .mtx = PTHREAD_MUTEX_INITIALIZER, + .once = PTHREAD_ONCE_INIT, + .init = sss_pam_mt_init }; + + +/* Wrappers for robust mutex support */ +static int sss_mutexattr_setrobust (pthread_mutexattr_t *attr) +{ +#ifdef HAVE_PTHREAD_MUTEXATTR_SETROBUST + return pthread_mutexattr_setrobust(attr, PTHREAD_MUTEX_ROBUST); +#elif HAVE_PTHREAD_MUTEXATTR_SETROBUST_NP + return pthread_mutexattr_setrobust_np(attr, PTHREAD_MUTEX_ROBUST_NP); +#else +#warning Robust mutexes are not supported on this platform. + return 0; +#endif +} + +static int sss_mutex_consistent(pthread_mutex_t *mtx) +{ +#ifdef HAVE_PTHREAD_MUTEX_CONSISTENT + return pthread_mutex_consistent(mtx); +#elif HAVE_PTHREAD_MUTEX_CONSISTENT_NP + return pthread_mutex_consistent_np(mtx); +#else +#warning Robust mutexes are not supported on this platform. + return 0; +#endif +} + +/* Generic mutex init, lock, unlock functions */ +static void sss_mt_init(struct sss_mutex *m) +{ + pthread_mutexattr_t attr; + + if (pthread_mutexattr_init(&attr) != 0) { + return; + } + if (sss_mutexattr_setrobust(&attr) != 0) { + return; + } + + pthread_mutex_init(&m->mtx, &attr); + pthread_mutexattr_destroy(&attr); +} + +static void sss_mt_lock(struct sss_mutex *m) +{ + pthread_once(&m->once, m->init); + if (pthread_mutex_lock(&m->mtx) == EOWNERDEAD) { + sss_cli_close_socket(); + sss_mutex_consistent(&m->mtx); + } +} + +static void sss_mt_unlock(struct sss_mutex *m) +{ + pthread_mutex_unlock(&m->mtx); +} + +/* NSS mutex wrappers */ +static void sss_nss_mt_init(void) +{ + sss_mt_init(&sss_nss_mtx); +} void sss_nss_lock(void) { - pthread_mutex_lock(&sss_nss_mutex); + sss_mt_lock(&sss_nss_mtx); } void sss_nss_unlock(void) { - pthread_mutex_unlock(&sss_nss_mutex); + sss_mt_unlock(&sss_nss_mtx); +} + +/* NSS mutex wrappers */ +static void sss_pam_mt_init(void) +{ + sss_mt_init(&sss_pam_mtx); } void sss_pam_lock(void) { - pthread_mutex_lock(&sss_pam_mutex); + sss_mt_lock(&sss_pam_mtx); } void sss_pam_unlock(void) { - pthread_mutex_unlock(&sss_pam_mutex); + sss_mt_unlock(&sss_pam_mtx); } #else -- cgit