Index: libfreeipmi/libcommon/ipmi-crypt.c =================================================================== --- libfreeipmi/libcommon/ipmi-crypt.c (revision 10162) +++ libfreeipmi/libcommon/ipmi-crypt.c (working copy) @@ -43,6 +43,11 @@ static int crypt_initialized = 0; #ifdef WITH_ENCRYPTION +static pthread_mutex_t gcrypt_thread_initialized_mutex = PTHREAD_MUTEX_INITIALIZER; +static int gcrypt_thread_initialized = 0; +#endif /* !WITH_ENCRYPTION */ + +#ifdef WITH_ENCRYPTION static int _gpg_error_to_errno (gcry_error_t e) { @@ -59,11 +64,35 @@ { #ifdef WITH_ENCRYPTION gcry_error_t e; + int perr; + + /* achu: + * + * For reasons that are unclear to me, gcry_control and + * GCRYCTL_SET_THREAD_CBS are no longer reentrant starting with + * libgcrypt 1.6.0. Calling it simultaneously leads to segfaults. + * + */ + if ((perr = pthread_mutex_lock (&gcrypt_thread_initialized_mutex))) + { + errno = perr; + return (-1); + } - if ((e = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread)) != GPG_ERR_NO_ERROR) + if (!gcrypt_thread_initialized) { - ERR_TRACE (gcry_strerror (e), e); - SET_ERRNO (_gpg_error_to_errno (e)); + if ((e = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread)) != GPG_ERR_NO_ERROR) + { + ERR_TRACE (gcry_strerror (e), e); + SET_ERRNO (_gpg_error_to_errno (e)); + return (-1); + } + gcrypt_thread_initialized++; + } + + if ((perr = pthread_mutex_unlock (&gcrypt_thread_initialized_mutex))) + { + errno = perr; return (-1); } Index: libfreeipmi/Makefile.am =================================================================== --- libfreeipmi/Makefile.am (revision 10162) +++ libfreeipmi/Makefile.am (working copy) @@ -31,6 +31,7 @@ libfreeipmi_la_LDFLAGS = \ -version-info @LIBFREEIPMI_VERSION_INFO@ $(VERSION_FLAGS) \ $(OTHER_FLAGS) \ + $(PTHREAD_LIBS) \ @GCRYPT_LIBS@ \ -lm Index: ChangeLog =================================================================== --- ChangeLog (revision 10162) +++ ChangeLog (working copy) @@ -1,3 +1,10 @@ +2015-01-06 Albert Chu + + * libfreeipmi/libcommon/ipmi-crypt.c (crypt_init): Only call + gcry_control w/ GCRYCTL_SET_THREAD_CBS once. It appears newer + version of libgcrypt cannot handle entering this function + simulatenously by multiple threads, leading to segfaults. + 2014-12-10 Albert Chu * ipmi-config/ipmi-config-category-core-user-sections.c (_set_user_access):