From 4e0d4d7cf3e630fbde187c506799048a3f359fc1 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Thu, 9 May 2002 03:38:12 +0000 Subject: doc/ 2002-05-09 Marcus Brinkmann * gpgme.texi (Overview): Replace note about thread-safeness. (Multi Threading): New section. gpgme/ 2002-05-08 Marcus Brinkmann * w32-util.c: New static variable GET_PATH_LOCK. (_gpgme_get_gpg_path): Remove superfluous NULL initializer. Take lock while determining path. (_gpgme_get_gpgsm_path): Likewise. * version.c (do_subsystem_inits): Set DONE to 1 after initialization. (gpgme_get_engine_info): New variable ENGINE_INFO_LOCK. Take lock while determining engine info. * rungpg.c (_gpgme_gpg_get_version): New variable GPG_VERSION_LOCK. Take the lock while determining the program version. * posix-io.c: Include "sema.h". (_gpgme_io_spawn): New variable FIXED_SIGNALS_LOCK. Take the lock while fixing the signals. (_gpgme_io_select): Make READFDS and WRITEFDS non-static. * key.c: Include "sema.h". New globals KEY_CACHE_LOCK and KEY_REF_LOCK. (capabilities_to_string): Make STRINGS very const. (_gpgme_key_cache_add): Lock the key cache. (_gpgme_key_cache_get): Likewise. (gpgme_key_ref, gpgme_key_release): Lock the key_ref_lock. * import.c (append_xml_impinfo): Make IMPORTED_FIELDS and IMPORT_RES_FIELDS very const. Make FIELD and FIELD_NAME a litle const. * engine.c (_gpgme_engine_get_info): New variable ENGINE_INFO_LOCK. Take lock while determining engine info. * engine-gpgsm.c: Include "sema.h". (_gpgme_gpgsm_get_version): New variable GPGSM_VERSION_LOCK. Take lock while getting program version. --- doc/ChangeLog | 5 ++++ doc/gpgme.texi | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 85 insertions(+), 5 deletions(-) (limited to 'doc') diff --git a/doc/ChangeLog b/doc/ChangeLog index 19b141e5..a5c7c5e0 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,8 @@ +2002-05-09 Marcus Brinkmann + + * gpgme.texi (Overview): Replace note about thread-safeness. + (Multi Threading): New section. + 2002-05-03 Werner Koch * gpgme.texi (Manipulating Data Buffers): Changed some data types diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 0061274b..9606eedd 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -104,6 +104,7 @@ Preparation * Header:: What header file you need to include. * Building the Source:: Compiler options to be used. * Library Version Check:: Getting and verifying the library version. +* Multi Threading:: How GPGME can be used in an MT environment. Protocols and Engines @@ -278,11 +279,9 @@ including listing keys, querying their attributes, generating, importing, exporting and deleting keys, and acquiring information about the trust path. -@cindex thread-safeness -@cindex multi-threading -@strong{Caution:} The @acronym{GPGME} library is not thread-safe. It -will be to some extent in the future, but currently great care has to -be taken if @acronym{GPGME} is used in a multi-threaded environment. +With some precautions, @acronym{GPGME} can be used in a multi-threaded +environment, although it is not completely thread safe and thus needs +the support of the application. @node Preparation @@ -298,6 +297,7 @@ of the library are verified. * Header:: What header file you need to include. * Building the Source:: Compiler options to be used. * Library Version Check:: Getting and verifying the library version. +* Multi Threading:: How GPGME can be used in an MT environment. @end menu @@ -402,6 +402,81 @@ features are provided by the installed version of the library. @end deftypefun +@node Multi Threading +@section Multi Threading +@cindex thread-safeness +@cindex multi-threading + +The @acronym{GPGME} library is not entirely thread-safe, but it can +still be used in a multi-threaded environment if some care is taken. +If the following requirements are met, there should be no race +conditions to worry about: + +@itemize @bullet +@item +The function @code{gpgme_check_version} must be called before any +other function in the library, because it initializes the locking +subsystem in @acronym{GPGME}. To achieve this in all generality, it +is necessary to synchronize the call to this function with all other +calls to functions in the library, using the synchronization +mechanisms available in your thread library. Otherwise, specific +compiler or CPU memory cache optimizations could lead to the situation +where a thread is started and uses @acronym{GPGME} before the effects +of the initialization are visible for this thread. It doesn't even +suffice to call @code{gpgme_check_version} before creating this other +thread@footnote{In SMP systems the new thread could be started on +another CPU before the effects of the initialization are seen by that +CPU's memory cache. Not doing proper synchronization here leads to +the same problems the double-checked locking idiom has. You might +find that if you don't do proper synchronization, it still works in +most configurations. Don't let this fool you. Someday it might lead +to subtle bugs when someone tries it on a DEC Alpha or an SMP +machine.}. + +For example, if you are using POSIX threads, each thread that wants to +call functions in @acronym{GPGME} could call the following function +before any function in the library: + +@example +#include + +void +initialize_gpgme (void) +{ + static int gpgme_init; + static pthread_mutext_t gpgme_init_lock = PTHREAD_MUTEX_INITIALIZER; + + pthread_mutex_lock (&gpgme_init_lock); + if (!gpgme_init) + { + gpgme_check_version (); + gpgme_init = 1; + } + pthread_mutex_unlock (&gpgme_init_lock); +} +@end example + +@item +Any @code{GpgmeData}, @code{GpgmeCtx} and @code{GpgmeRecipients} +object must only be accessed by one thread at a time. If multiple +threads want to deal with the same object, the caller has to make sure +that operations on this object are fully synchronized. + +@item +Only one thread is allowed to call @code{gpgme_wait} at a time. If +multiple threads call this function, the caller must make sure that +all invocations are fully synchronized. + +@item +Unfortunately, the last rule implies that all calls to one of the +following functions have to be fully synchronized together with +@code{gpgme_wait}, as they call @code{gpgme_wait} internally: All +functions @code{gpgme_op_FOO} that have a corresponding +@code{gpgme_op_FOO_start} function, @code{gpgme_op_keylist_next}, +@code{gpgme_op_trustlist_next}. +@end itemize + + @node Protocols and Engines @chapter Protocols and Engines @cindex protocol -- cgit v1.2.3