This was originally reported as a Firefox crash when printing through the CUPS
library.
Here is the description by Caolan McNamara:
a) firefox dlopens cups
b) cups calls...
gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
gnutls_global_init();
Due to rhb#544619# the idea was to ensure that libgcrypt gets locked to avoid
multiple threads using neon (that itself may use libgcrypt) from trampling over
their shared libgcrypt. Hence the gcry_control added to cups (along the lines
suggested at
http://www.gnupg.org/documentation/manuals/gcrypt/Multi_002dThreading.html) to
make sure that if cups + neon is used in an app and cups is used first then all
works well if multiple threads use neon later one.
c) firefox dlcloses cups
d) firefox dlopens cups
e) cups calls...
gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
gnutls_global_init();
In libgcrypt's src/global.c
case GCRYCTL_SET_THREAD_CBS: err = ath_install (va_arg (arg_ptr, void *), any_init_done);
any_init_done is still true from the *last* init, and ath_install is
effectively a no-op if any_init_done is true. So the new pthread stuff isn't
installed, and libgcrypt still points to the old info which was destroyed at
the first dlclose of cups.
Its all a bit unfortunate. If e.g. libgcrypt had way to query the
GCRYCTL_SET_THREAD_CBS info then libs using it could either
a) store a copy of the old info if it existed, install their own on their init
and restore the old one on their deinit.
b) only install one if one didn't exist (possible now) and *remove* their one
on deinit (not possible now)
Its not really practical in general of course for the *app* to call
gcry_control (GCRYCTL_SET_THREAD_CBS...) because how is it to know that
libgcrypt is being used by any of its libraries. Though that would solve the
problem in this case seeing as any other GCRYCTL_SET_THREAD_CBS would be
ignored, and the one installed during dlopen of cups wouldn't apply.
So long and short of it is that it's currently hopeless to use
GCRYCTL_SET_THREAD_CBS in a library because that library can be dlclosed,
destroying the locking functions that were installed into libgcrypt.
See also:
https://bugzilla.redhat.com/show_bug.cgi?id=553834
and
https://bugzilla.redhat.com/show_bug.cgi?id=569803