summaryrefslogtreecommitdiff
path: root/src/sss_client
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2012-08-13 15:30:39 +0200
committerJakub Hrozek <jhrozek@redhat.com>2012-08-27 16:32:01 +0200
commit86b61156743b7ebdc049450a6f88452890fd9a61 (patch)
treeb155c68344e2adda5085047eee3f7dd5e98f6bcc /src/sss_client
parentfd2840c15ce480ef017ce880a6ac8b10e22ae9d2 (diff)
downloadsssd-86b61156743b7ebdc049450a6f88452890fd9a61.tar.gz
sssd-86b61156743b7ebdc049450a6f88452890fd9a61.tar.bz2
sssd-86b61156743b7ebdc049450a6f88452890fd9a61.zip
Use PTHREAD_MUTEX_ROBUST to avoid deadlock in the client
https://fedorahosted.org/sssd/ticket/1460
Diffstat (limited to 'src/sss_client')
-rw-r--r--src/sss_client/common.c96
1 files changed, 90 insertions, 6 deletions
diff --git a/src/sss_client/common.c b/src/sss_client/common.c
index 59eae3b1..5b175159 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