core: Use gpgrt locking for thread safeness
* configure.ac: Require libgpg-error 1.17. No longer check for pthread. * doc/gpgme.texi: Document removed neccessity for thread safe gpgme flavours. * src/sema.h (DEFINE_GLOBAL_LOCK), (DEFINE_STATIC_LOCK, INIT_LOCK, DECLARE_LOCK) (DESTROY_LOCK, LOCK, UNLOCK): Change to gpgrt equivalents. * src/posix-sema.c, src/w32-sema.c: Removed. * src/Makefile.am: Remove libpthread and Update accordingly. * src/ath.c, src/ath.h (ath_mutex_init) (ath_mutex_destroy, ath_mutex_lock, ath_mutex_unlock): Removed. * src/ath.h (ATH_MUTEX_INITIALIZER): Removed. * src/version.c (do_subsystem_inits): sema_subsystem_init is no longer required. * tests/gpg/Makefile.am: Add new threading tests. (t_thread1_LDADD, t_cancel_LDADD): Use just gpgme. * tests/gpg/t-thread-keylist-verify.c, tests/gpg/t-thread-keylist.c: New. * src/gpgme-config.in: Use -lgpgme for thread-model pthread. -- Using gpgrt locks instead of pthread locks removes the neccessity to link pthread directly to gpgme and have a different, thread safe flavor of gpgme. Now gpgme is thread-safe if the conditions mentioned in the doc are met. As the cpp bindings linked against libgpgme and not libgpgme-pthread this fixes threading problems with them. libgpgme-pthread is removed but gpgme-config still supports --thread=pthread for compatibility with find scripts.
This commit is contained in:
parent
f1f341062e
commit
09b6455432
10
configure.ac
10
configure.ac
@ -71,7 +71,7 @@ LIBQGPGME_LT_REVISION=0
|
|||||||
GPGME_CONFIG_API_VERSION=1
|
GPGME_CONFIG_API_VERSION=1
|
||||||
##############################################
|
##############################################
|
||||||
|
|
||||||
NEED_GPG_ERROR_VERSION=1.11
|
NEED_GPG_ERROR_VERSION=1.17
|
||||||
NEED_LIBASSUAN_API=2
|
NEED_LIBASSUAN_API=2
|
||||||
NEED_LIBASSUAN_VERSION=2.0.2
|
NEED_LIBASSUAN_VERSION=2.0.2
|
||||||
|
|
||||||
@ -211,11 +211,6 @@ case "${host}" in
|
|||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
|
||||||
AC_CHECK_LIB(pthread,pthread_create,have_pthread=yes)
|
|
||||||
if test "$have_pthread" = yes; then
|
|
||||||
AC_DEFINE(HAVE_PTHREAD, ,[Define if we have pthread.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
# XXX: Probably use exec-prefix here?
|
# XXX: Probably use exec-prefix here?
|
||||||
# GPG_DEFAULT='/usr/bin/gpg'
|
# GPG_DEFAULT='/usr/bin/gpg'
|
||||||
# GPGSM_DEFAULT='/usr/bin/gpgsm'
|
# GPGSM_DEFAULT='/usr/bin/gpgsm'
|
||||||
@ -257,8 +252,6 @@ AM_CONDITIONAL(HAVE_ANDROID_SYSTEM, test "$have_android_system" = yes)
|
|||||||
|
|
||||||
AM_CONDITIONAL(BUILD_W32_GLIB, test "$build_w32_glib" = yes)
|
AM_CONDITIONAL(BUILD_W32_GLIB, test "$build_w32_glib" = yes)
|
||||||
|
|
||||||
AM_CONDITIONAL(HAVE_PTHREAD, test "$have_pthread" = "yes")
|
|
||||||
|
|
||||||
|
|
||||||
AC_ARG_ENABLE([fixed-path],
|
AC_ARG_ENABLE([fixed-path],
|
||||||
AC_HELP_STRING([--enable-fixed-path=PATH],
|
AC_HELP_STRING([--enable-fixed-path=PATH],
|
||||||
@ -905,7 +898,6 @@ echo "
|
|||||||
|
|
||||||
UI Server: $uiserver
|
UI Server: $uiserver
|
||||||
FD Passing: $use_descriptor_passing
|
FD Passing: $use_descriptor_passing
|
||||||
GPGME Pthread: $have_pthread
|
|
||||||
|
|
||||||
Language bindings: ${enabled_languages_v:-$enabled_languages}
|
Language bindings: ${enabled_languages_v:-$enabled_languages}
|
||||||
"
|
"
|
||||||
|
@ -458,12 +458,6 @@ specifying both options to @command{gpgme-config}:
|
|||||||
gcc -o foo foo.c `gpgme-config --cflags --libs`
|
gcc -o foo foo.c `gpgme-config --cflags --libs`
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
If you want to link to one of the thread-safe versions of
|
|
||||||
@acronym{GPGME}, you must specify the @option{--thread} option before
|
|
||||||
any other option to select the thread package you want to link with.
|
|
||||||
Supported thread packages are @option{--thread=pth} and
|
|
||||||
@option{--thread=pthread}.
|
|
||||||
|
|
||||||
If you need to detect the installed language bindings you can use list
|
If you need to detect the installed language bindings you can use list
|
||||||
them using:
|
them using:
|
||||||
|
|
||||||
@ -614,7 +608,9 @@ that can be used with GNU Pth, and defines @code{GPGME_PTH_CFLAGS} and
|
|||||||
|
|
||||||
@code{AM_PATH_GPGME_PTHREAD} checks for the version of @acronym{GPGME}
|
@code{AM_PATH_GPGME_PTHREAD} checks for the version of @acronym{GPGME}
|
||||||
that can be used with the native pthread implementation, and defines
|
that can be used with the native pthread implementation, and defines
|
||||||
@code{GPGME_PTHREAD_CFLAGS} and @code{GPGME_PTHREAD_LIBS}.
|
@code{GPGME_PTHREAD_CFLAGS} and @code{GPGME_PTHREAD_LIBS}. Since
|
||||||
|
version 1.8.0 this is no longer required to GPGME_PTHREAD as
|
||||||
|
@acronym{GPGME} itself is thread safe.
|
||||||
|
|
||||||
This macro searches for @command{gpgme-config} along the PATH. If
|
This macro searches for @command{gpgme-config} along the PATH. If
|
||||||
you are cross-compiling, it is useful to set the environment variable
|
you are cross-compiling, it is useful to set the environment variable
|
||||||
@ -814,31 +810,11 @@ application is multi-threaded, and you install a signal action for
|
|||||||
@cindex thread-safeness
|
@cindex thread-safeness
|
||||||
@cindex multi-threading
|
@cindex multi-threading
|
||||||
|
|
||||||
The @acronym{GPGME} library is not entirely thread-safe, but it can
|
The @acronym{GPGME} library is mostly thread-safe, an can be used
|
||||||
still be used in a multi-threaded environment if some care is taken.
|
in a mulithreaded environment but there are some requirements
|
||||||
If the following requirements are met, there should be no race
|
for mutlithreaded use:
|
||||||
conditions to worry about:
|
|
||||||
|
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item
|
|
||||||
@acronym{GPGME} supports the thread libraries pthread and GNU Pth.
|
|
||||||
The support for this has to be enabled at compile time.
|
|
||||||
@acronym{GPGME} will automatically detect the location in which the
|
|
||||||
thread libraries are installed and activate the support for them at
|
|
||||||
build time.
|
|
||||||
|
|
||||||
Support for other thread libraries is very easy to add. Please
|
|
||||||
contact us if you have the need.
|
|
||||||
|
|
||||||
@item
|
|
||||||
If you want to use @acronym{GPGME} with threads, you must link to the
|
|
||||||
right version of the library. The name of the right library is
|
|
||||||
@code{libgpgme-} followed by the name of the thread package you use.
|
|
||||||
For example, if you use GNU Pth, the right name is
|
|
||||||
@code{libgpgme-pth}. Use the Automake macros or
|
|
||||||
@command{gpgme-config} program for simplicity.
|
|
||||||
|
|
||||||
|
|
||||||
@item
|
@item
|
||||||
The function @code{gpgme_check_version} must be called before any
|
The function @code{gpgme_check_version} must be called before any
|
||||||
other function in the library, because it initializes the thread
|
other function in the library, because it initializes the thread
|
||||||
|
@ -28,20 +28,13 @@ nodist_include_HEADERS = gpgme.h
|
|||||||
|
|
||||||
bin_PROGRAMS = gpgme-tool
|
bin_PROGRAMS = gpgme-tool
|
||||||
|
|
||||||
if HAVE_PTHREAD
|
|
||||||
ltlib_gpgme_pthread = libgpgme-pthread.la
|
|
||||||
else
|
|
||||||
ltlib_gpgme_pthread =
|
|
||||||
endif
|
|
||||||
|
|
||||||
if BUILD_W32_GLIB
|
if BUILD_W32_GLIB
|
||||||
ltlib_gpgme_glib = libgpgme-glib.la
|
ltlib_gpgme_glib = libgpgme-glib.la
|
||||||
else
|
else
|
||||||
ltlib_gpgme_glib =
|
ltlib_gpgme_glib =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
lib_LTLIBRARIES = libgpgme.la $(ltlib_gpgme_glib) $(ltlib_gpgme_qt) \
|
lib_LTLIBRARIES = libgpgme.la $(ltlib_gpgme_glib)
|
||||||
$(ltlib_gpgme_pthread)
|
|
||||||
|
|
||||||
if HAVE_LD_VERSION_SCRIPT
|
if HAVE_LD_VERSION_SCRIPT
|
||||||
libgpgme_version_script_cmd = -Wl,--version-script=$(srcdir)/libgpgme.vers
|
libgpgme_version_script_cmd = -Wl,--version-script=$(srcdir)/libgpgme.vers
|
||||||
@ -50,10 +43,10 @@ libgpgme_version_script_cmd =
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
if HAVE_DOSISH_SYSTEM
|
if HAVE_DOSISH_SYSTEM
|
||||||
system_components = w32-util.c w32-sema.c
|
system_components = w32-util.c
|
||||||
system_components_not_extra = w32-io.c
|
system_components_not_extra = w32-io.c
|
||||||
else
|
else
|
||||||
system_components = ath.h posix-util.c posix-sema.c posix-io.c
|
system_components = ath.h posix-util.c posix-io.c
|
||||||
system_components_not_extra =
|
system_components_not_extra =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -93,12 +86,10 @@ main_sources = \
|
|||||||
engine-spawn.c \
|
engine-spawn.c \
|
||||||
gpgconf.c queryswdb.c \
|
gpgconf.c queryswdb.c \
|
||||||
sema.h priv-io.h $(system_components) sys-util.h dirinfo.c \
|
sema.h priv-io.h $(system_components) sys-util.h dirinfo.c \
|
||||||
debug.c debug.h gpgme.c version.c error.c
|
debug.c debug.h gpgme.c version.c error.c \
|
||||||
|
|
||||||
libgpgme_la_SOURCES = $(main_sources) \
|
|
||||||
ath.h ath.c $(system_components_not_extra)
|
ath.h ath.c $(system_components_not_extra)
|
||||||
libgpgme_pthread_la_SOURCES = $(main_sources) \
|
|
||||||
ath.h ath-pthread.c $(system_components_not_extra)
|
libgpgme_la_SOURCES = $(main_sources)
|
||||||
|
|
||||||
if BUILD_W32_GLIB
|
if BUILD_W32_GLIB
|
||||||
libgpgme_glib_la_SOURCES = $(main_sources) ath.h ath.c w32-glib-io.c
|
libgpgme_glib_la_SOURCES = $(main_sources) ath.h ath.c w32-glib-io.c
|
||||||
@ -163,14 +154,6 @@ libgpgme_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
|
|||||||
libgpgme_la_LIBADD = $(gpgme_res) @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
libgpgme_la_LIBADD = $(gpgme_res) @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
||||||
@GPG_ERROR_LIBS@
|
@GPG_ERROR_LIBS@
|
||||||
|
|
||||||
libgpgme_pthread_la_LDFLAGS = \
|
|
||||||
$(no_undefined) $(export_symbols) $(extra_ltoptions) \
|
|
||||||
$(libgpgme_version_script_cmd) -version-info \
|
|
||||||
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
|
||||||
libgpgme_pthread_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers
|
|
||||||
libgpgme_pthread_la_LIBADD = $(gpgme_res) @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
|
||||||
-lpthread @GPG_ERROR_LIBS@
|
|
||||||
|
|
||||||
if BUILD_W32_GLIB
|
if BUILD_W32_GLIB
|
||||||
libgpgme_glib_la_LDFLAGS = \
|
libgpgme_glib_la_LDFLAGS = \
|
||||||
$(no_undefined) $(export_symbols) $(extra_ltoptions) \
|
$(no_undefined) $(export_symbols) $(extra_ltoptions) \
|
||||||
|
@ -1,188 +0,0 @@
|
|||||||
/* ath-pthread.c - pthread module for self-adapting thread-safeness library
|
|
||||||
Copyright (C) 2002, 2003, 2004 g10 Code GmbH
|
|
||||||
|
|
||||||
This file is part of GPGME.
|
|
||||||
|
|
||||||
GPGME is free software; you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU Lesser General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2.1 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
GPGME is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
||||||
02111-1307, USA. */
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#ifdef HAVE_UNISTD_H
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_SELECT_H
|
|
||||||
# include <sys/select.h>
|
|
||||||
#else
|
|
||||||
# ifdef HAVE_SYS_TIME_H
|
|
||||||
# include <sys/time.h>
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#include "gpgme.h"
|
|
||||||
|
|
||||||
#include "ath.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* The lock we take while checking for lazy lock initialization. */
|
|
||||||
static pthread_mutex_t check_init_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
|
|
||||||
/* Initialize the mutex *PRIV. If JUST_CHECK is true, only do this if
|
|
||||||
it is not already initialized. */
|
|
||||||
static int
|
|
||||||
mutex_pthread_init (ath_mutex_t *priv, int just_check)
|
|
||||||
{
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
if (just_check)
|
|
||||||
pthread_mutex_lock (&check_init_lock);
|
|
||||||
if (!*priv || !just_check)
|
|
||||||
{
|
|
||||||
pthread_mutex_t *lock = malloc (sizeof (pthread_mutex_t));
|
|
||||||
if (!lock)
|
|
||||||
err = ENOMEM;
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
err = pthread_mutex_init (lock, NULL);
|
|
||||||
if (err)
|
|
||||||
free (lock);
|
|
||||||
else
|
|
||||||
*priv = (ath_mutex_t) lock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (just_check)
|
|
||||||
pthread_mutex_unlock (&check_init_lock);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ath_init (void)
|
|
||||||
{
|
|
||||||
/* Nothing to do. */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uintptr_t
|
|
||||||
ath_self (void)
|
|
||||||
{
|
|
||||||
return (uintptr_t) pthread_self ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
ath_mutex_init (ath_mutex_t *lock)
|
|
||||||
{
|
|
||||||
return mutex_pthread_init (lock, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
ath_mutex_destroy (ath_mutex_t *lock)
|
|
||||||
{
|
|
||||||
int err = mutex_pthread_init (lock, 1);
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
err = pthread_mutex_destroy ((pthread_mutex_t *) *lock);
|
|
||||||
free (*lock);
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
ath_mutex_lock (ath_mutex_t *lock)
|
|
||||||
{
|
|
||||||
int ret = mutex_pthread_init (lock, 1);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return pthread_mutex_lock ((pthread_mutex_t *) *lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
ath_mutex_unlock (ath_mutex_t *lock)
|
|
||||||
{
|
|
||||||
int ret = mutex_pthread_init (lock, 1);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return pthread_mutex_unlock ((pthread_mutex_t *) *lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
gpgme_ssize_t
|
|
||||||
ath_read (int fd, void *buf, size_t nbytes)
|
|
||||||
{
|
|
||||||
return read (fd, buf, nbytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
gpgme_ssize_t
|
|
||||||
ath_write (int fd, const void *buf, size_t nbytes)
|
|
||||||
{
|
|
||||||
return write (fd, buf, nbytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
gpgme_ssize_t
|
|
||||||
ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
|
|
||||||
struct timeval *timeout)
|
|
||||||
{
|
|
||||||
return select (nfd, rset, wset, eset, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
gpgme_ssize_t
|
|
||||||
ath_waitpid (pid_t pid, int *status, int options)
|
|
||||||
{
|
|
||||||
return waitpid (pid, status, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
ath_accept (int s, struct sockaddr *addr, socklen_t *length_ptr)
|
|
||||||
{
|
|
||||||
return accept (s, addr, length_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
ath_connect (int s, const struct sockaddr *addr, socklen_t length)
|
|
||||||
{
|
|
||||||
return connect (s, addr, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ath_sendmsg (int s, const struct msghdr *msg, int flags)
|
|
||||||
{
|
|
||||||
return sendmsg (s, msg, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
ath_recvmsg (int s, struct msghdr *msg, int flags)
|
|
||||||
{
|
|
||||||
return recvmsg (s, msg, flags);
|
|
||||||
}
|
|
51
src/ath.c
51
src/ath.c
@ -49,11 +49,6 @@
|
|||||||
#include "ath.h"
|
#include "ath.h"
|
||||||
|
|
||||||
|
|
||||||
#define MUTEX_UNLOCKED ((ath_mutex_t) 0)
|
|
||||||
#define MUTEX_LOCKED ((ath_mutex_t) 1)
|
|
||||||
#define MUTEX_DESTROYED ((ath_mutex_t) 2)
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
uintptr_t
|
uintptr_t
|
||||||
@ -80,52 +75,6 @@ ath_self (void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
ath_mutex_init (ath_mutex_t *lock)
|
|
||||||
{
|
|
||||||
#ifndef NDEBUG
|
|
||||||
*lock = MUTEX_UNLOCKED;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
ath_mutex_destroy (ath_mutex_t *lock)
|
|
||||||
{
|
|
||||||
#ifndef NDEBUG
|
|
||||||
assert (*lock == MUTEX_UNLOCKED);
|
|
||||||
|
|
||||||
*lock = MUTEX_DESTROYED;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
ath_mutex_lock (ath_mutex_t *lock)
|
|
||||||
{
|
|
||||||
#ifndef NDEBUG
|
|
||||||
assert (*lock == MUTEX_UNLOCKED);
|
|
||||||
|
|
||||||
*lock = MUTEX_LOCKED;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
ath_mutex_unlock (ath_mutex_t *lock)
|
|
||||||
{
|
|
||||||
#ifndef NDEBUG
|
|
||||||
assert (*lock == MUTEX_LOCKED);
|
|
||||||
|
|
||||||
*lock = MUTEX_UNLOCKED;
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
gpgme_ssize_t
|
gpgme_ssize_t
|
||||||
ath_read (int fd, void *buf, size_t nbytes)
|
ath_read (int fd, void *buf, size_t nbytes)
|
||||||
{
|
{
|
||||||
|
13
src/ath.h
13
src/ath.h
@ -60,10 +60,6 @@
|
|||||||
#define _ATH_PREFIX1(x,y) x ## y
|
#define _ATH_PREFIX1(x,y) x ## y
|
||||||
#define _ATH_PREFIX2(x,y) _ATH_PREFIX1(x,y)
|
#define _ATH_PREFIX2(x,y) _ATH_PREFIX1(x,y)
|
||||||
#define _ATH_PREFIX(x) _ATH_PREFIX2(_ATH_EXT_SYM_PREFIX,x)
|
#define _ATH_PREFIX(x) _ATH_PREFIX2(_ATH_EXT_SYM_PREFIX,x)
|
||||||
#define ath_mutex_init _ATH_PREFIX(ath_mutex_init)
|
|
||||||
#define ath_mutex_destroy _ATH_PREFIX(ath_mutex_destroy)
|
|
||||||
#define ath_mutex_lock _ATH_PREFIX(ath_mutex_lock)
|
|
||||||
#define ath_mutex_unlock _ATH_PREFIX(ath_mutex_unlock)
|
|
||||||
#define ath_read _ATH_PREFIX(ath_read)
|
#define ath_read _ATH_PREFIX(ath_read)
|
||||||
#define ath_write _ATH_PREFIX(ath_write)
|
#define ath_write _ATH_PREFIX(ath_write)
|
||||||
#define ath_select _ATH_PREFIX(ath_select)
|
#define ath_select _ATH_PREFIX(ath_select)
|
||||||
@ -75,17 +71,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef void *ath_mutex_t;
|
|
||||||
#define ATH_MUTEX_INITIALIZER 0;
|
|
||||||
|
|
||||||
uintptr_t ath_self (void);
|
uintptr_t ath_self (void);
|
||||||
|
|
||||||
/* Functions for mutual exclusion. */
|
|
||||||
int ath_mutex_init (ath_mutex_t *mutex);
|
|
||||||
int ath_mutex_destroy (ath_mutex_t *mutex);
|
|
||||||
int ath_mutex_lock (ath_mutex_t *mutex);
|
|
||||||
int ath_mutex_unlock (ath_mutex_t *mutex);
|
|
||||||
|
|
||||||
/* Replacement for the POSIX functions, which can be used to allow
|
/* Replacement for the POSIX functions, which can be used to allow
|
||||||
other (user-level) threads to run. */
|
other (user-level) threads to run. */
|
||||||
gpgme_ssize_t ath_read (int fd, void *buf, size_t nbytes);
|
gpgme_ssize_t ath_read (int fd, void *buf, size_t nbytes);
|
||||||
|
@ -32,7 +32,9 @@ gpg_error_libs="@GPG_ERROR_LIBS@"
|
|||||||
# Configure thread packages.
|
# Configure thread packages.
|
||||||
thread_modules=""
|
thread_modules=""
|
||||||
|
|
||||||
@HAVE_PTHREAD_TRUE@thread_modules="$thread_modules pthread"
|
# For compatibility we keep proving the
|
||||||
|
# thread modules variable.
|
||||||
|
thread_modules="$thread_modules pthread"
|
||||||
libs_pthread="-lpthread"
|
libs_pthread="-lpthread"
|
||||||
cflags_pthread=""
|
cflags_pthread=""
|
||||||
|
|
||||||
@ -50,7 +52,6 @@ usage()
|
|||||||
cat <<EOF
|
cat <<EOF
|
||||||
Usage: gpgme-config [OPTIONS]
|
Usage: gpgme-config [OPTIONS]
|
||||||
Options:
|
Options:
|
||||||
--thread={${thread_modules}}]
|
|
||||||
--prefix
|
--prefix
|
||||||
--exec-prefix
|
--exec-prefix
|
||||||
--version
|
--version
|
||||||
@ -139,7 +140,8 @@ while test $# -gt 0; do
|
|||||||
result=
|
result=
|
||||||
tmp_x=
|
tmp_x=
|
||||||
case "$thread_module" in
|
case "$thread_module" in
|
||||||
pthread) tmp_l="-lgpgme-pthread"; tmp_x="$libs_pthread" ;;
|
# deprecated
|
||||||
|
pthread) tmp_l="-lgpgme" ;;
|
||||||
*)
|
*)
|
||||||
if test "x$with_glib" = "xyes" ; then
|
if test "x$with_glib" = "xyes" ; then
|
||||||
tmp_l="-lgpgme-glib"
|
tmp_l="-lgpgme-glib"
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
/* posix-sema.c
|
|
||||||
Copyright (C) 2001 Werner Koch (dd9jn)
|
|
||||||
Copyright (C) 2001, 2002, 2004, 2007 g10 Code GmbH
|
|
||||||
|
|
||||||
This file is part of GPGME.
|
|
||||||
|
|
||||||
GPGME is free software; you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU Lesser General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2.1 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
GPGME is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
||||||
02111-1307, USA. */
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#ifdef HAVE_UNISTD_H
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_TIME_H
|
|
||||||
# include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
|
||||||
# include <sys/types.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
#include "sema.h"
|
|
||||||
#include "ath.h"
|
|
||||||
|
|
||||||
void
|
|
||||||
_gpgme_sema_subsystem_init ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_gpgme_sema_cs_enter (struct critsect_s *s)
|
|
||||||
{
|
|
||||||
_gpgme_ath_mutex_lock (&s->priv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_gpgme_sema_cs_leave (struct critsect_s *s)
|
|
||||||
{
|
|
||||||
_gpgme_ath_mutex_unlock (&s->priv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_gpgme_sema_cs_destroy (struct critsect_s *s)
|
|
||||||
{
|
|
||||||
_gpgme_ath_mutex_destroy (&s->priv);
|
|
||||||
s->priv = NULL;
|
|
||||||
}
|
|
43
src/sema.h
43
src/sema.h
@ -22,46 +22,23 @@
|
|||||||
#ifndef SEMA_H
|
#ifndef SEMA_H
|
||||||
#define SEMA_H
|
#define SEMA_H
|
||||||
|
|
||||||
struct critsect_s
|
#include <gpg-error.h>
|
||||||
{
|
|
||||||
const char *name;
|
|
||||||
void *priv;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DEFINE_GLOBAL_LOCK(name) \
|
#define DEFINE_GLOBAL_LOCK(name) \
|
||||||
struct critsect_s name = { #name, NULL }
|
gpgrt_lock_t name = GPGRT_LOCK_INITIALIZER
|
||||||
|
|
||||||
#define DEFINE_STATIC_LOCK(name) \
|
#define DEFINE_STATIC_LOCK(name) \
|
||||||
static struct critsect_s name = { #name, NULL }
|
static gpgrt_lock_t name = GPGRT_LOCK_INITIALIZER
|
||||||
|
|
||||||
#define DECLARE_LOCK(name) \
|
#define INIT_LOCK(name) \
|
||||||
struct critsect_s name
|
name = (gpgrt_lock_t) GPGRT_LOCK_INITIALIZER
|
||||||
#define INIT_LOCK(a) \
|
|
||||||
do \
|
|
||||||
{ \
|
|
||||||
(a).name = #a; \
|
|
||||||
(a).priv = NULL; \
|
|
||||||
} \
|
|
||||||
while (0)
|
|
||||||
#define DESTROY_LOCK(name) _gpgme_sema_cs_destroy (&(name))
|
|
||||||
|
|
||||||
|
#define DECLARE_LOCK(name) gpgrt_lock_t name
|
||||||
|
|
||||||
#define LOCK(name) \
|
#define DESTROY_LOCK(name) gpgrt_lock_destroy(&name)
|
||||||
do \
|
|
||||||
{ \
|
|
||||||
_gpgme_sema_cs_enter (&(name)); \
|
|
||||||
} \
|
|
||||||
while (0)
|
|
||||||
|
|
||||||
#define UNLOCK(name) \
|
#define LOCK(name) gpgrt_lock_lock(&name)
|
||||||
do \
|
|
||||||
{ \
|
|
||||||
_gpgme_sema_cs_leave (&(name)); \
|
|
||||||
} \
|
|
||||||
while (0)
|
|
||||||
|
|
||||||
void _gpgme_sema_subsystem_init (void);
|
#define UNLOCK(name) gpgrt_lock_unlock(&name)
|
||||||
void _gpgme_sema_cs_enter (struct critsect_s *s);
|
|
||||||
void _gpgme_sema_cs_leave (struct critsect_s *s);
|
|
||||||
void _gpgme_sema_cs_destroy (struct critsect_s *s);
|
|
||||||
|
|
||||||
#endif /* SEMA_H */
|
#endif /* SEMA_H */
|
||||||
|
@ -74,7 +74,6 @@ do_subsystem_inits (void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_gpgme_sema_subsystem_init ();
|
|
||||||
_gpgme_debug_subsystem_init ();
|
_gpgme_debug_subsystem_init ();
|
||||||
_gpgme_io_subsystem_init ();
|
_gpgme_io_subsystem_init ();
|
||||||
_gpgme_status_init ();
|
_gpgme_status_init ();
|
||||||
|
117
src/w32-sema.c
117
src/w32-sema.c
@ -1,117 +0,0 @@
|
|||||||
/* w32-sema.c
|
|
||||||
Copyright (C) 2001 Werner Koch (dd9jn)
|
|
||||||
Copyright (C) 2001, 2002, 2004, 2007 g10 Code GmbH
|
|
||||||
|
|
||||||
This file is part of GPGME.
|
|
||||||
|
|
||||||
GPGME is free software; you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU Lesser General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2.1 of
|
|
||||||
the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
GPGME is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
||||||
02111-1307, USA. */
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#ifdef HAVE_SYS_TIME_H
|
|
||||||
# include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
|
||||||
# include <sys/types.h>
|
|
||||||
#endif
|
|
||||||
#include <io.h>
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
#include "sema.h"
|
|
||||||
#include "debug.h"
|
|
||||||
|
|
||||||
static void
|
|
||||||
sema_fatal (const char *text)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "sema.c: %s\n", text);
|
|
||||||
abort ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
critsect_init (struct critsect_s *s)
|
|
||||||
{
|
|
||||||
CRITICAL_SECTION *mp;
|
|
||||||
static CRITICAL_SECTION init_lock;
|
|
||||||
static int initialized;
|
|
||||||
|
|
||||||
if (!initialized) {
|
|
||||||
/* The very first time we call this function, we assume that
|
|
||||||
only one thread is running, so that we can bootstrap the
|
|
||||||
semaphore code. */
|
|
||||||
InitializeCriticalSection (&init_lock);
|
|
||||||
initialized = 1;
|
|
||||||
}
|
|
||||||
if (!s)
|
|
||||||
return; /* we just want to initialize ourself */
|
|
||||||
|
|
||||||
/* first test whether it is really not initialized */
|
|
||||||
EnterCriticalSection (&init_lock);
|
|
||||||
if ( s->priv ) {
|
|
||||||
LeaveCriticalSection (&init_lock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* now init it */
|
|
||||||
mp = malloc ( sizeof *mp );
|
|
||||||
if (!mp) {
|
|
||||||
LeaveCriticalSection (&init_lock);
|
|
||||||
sema_fatal ("out of core while creating critical section lock");
|
|
||||||
}
|
|
||||||
InitializeCriticalSection (mp);
|
|
||||||
s->priv = mp;
|
|
||||||
LeaveCriticalSection (&init_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_gpgme_sema_subsystem_init ()
|
|
||||||
{
|
|
||||||
/* fixme: we should check that there is only one thread running */
|
|
||||||
critsect_init (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
_gpgme_sema_cs_enter ( struct critsect_s *s )
|
|
||||||
{
|
|
||||||
if (!s->priv)
|
|
||||||
critsect_init (s);
|
|
||||||
EnterCriticalSection ( (CRITICAL_SECTION*)s->priv );
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_gpgme_sema_cs_leave (struct critsect_s *s)
|
|
||||||
{
|
|
||||||
if (!s->priv)
|
|
||||||
critsect_init (s);
|
|
||||||
LeaveCriticalSection ((CRITICAL_SECTION*)s->priv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_gpgme_sema_cs_destroy ( struct critsect_s *s )
|
|
||||||
{
|
|
||||||
if (s && s->priv) {
|
|
||||||
DeleteCriticalSection ((CRITICAL_SECTION*)s->priv);
|
|
||||||
free (s->priv);
|
|
||||||
s->priv = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
@ -38,7 +38,8 @@ c_tests = \
|
|||||||
t-encrypt t-encrypt-sym t-encrypt-sign t-sign t-signers \
|
t-encrypt t-encrypt-sym t-encrypt-sign t-sign t-signers \
|
||||||
t-decrypt t-verify t-decrypt-verify t-sig-notation t-export \
|
t-decrypt t-verify t-decrypt-verify t-sig-notation t-export \
|
||||||
t-import t-trustlist t-edit t-keylist t-keylist-sig t-wait \
|
t-import t-trustlist t-edit t-keylist t-keylist-sig t-wait \
|
||||||
t-encrypt-large t-file-name t-gpgconf t-encrypt-mixed $(tests_unix)
|
t-encrypt-large t-file-name t-gpgconf t-encrypt-mixed $(tests_unix) \
|
||||||
|
t-thread-keylist t-thread-keylist-verify
|
||||||
|
|
||||||
TESTS = initial.test $(c_tests) final.test
|
TESTS = initial.test $(c_tests) final.test
|
||||||
|
|
||||||
@ -61,8 +62,10 @@ EXTRA_DIST = initial.test final.test \
|
|||||||
AM_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_CFLAGS@
|
AM_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_CFLAGS@
|
||||||
AM_LDFLAGS = -no-install
|
AM_LDFLAGS = -no-install
|
||||||
LDADD = ../../src/libgpgme.la
|
LDADD = ../../src/libgpgme.la
|
||||||
t_thread1_LDADD = ../../src/libgpgme-pthread.la -lpthread
|
t_thread1_LDADD = ../../src/libgpgme.la -lpthread
|
||||||
t_cancel_LDADD = ../../src/libgpgme-pthread.la -lpthread
|
t_thread_keylist_LDADD = ../../src/libgpgme.la -lpthread
|
||||||
|
t_thread_keylist_verify_LDADD = ../../src/libgpgme.la -lpthread
|
||||||
|
t_cancel_LDADD = ../../src/libgpgme.la -lpthread
|
||||||
|
|
||||||
# We don't run t-genkey and t-cancel in the test suite, because it
|
# We don't run t-genkey and t-cancel in the test suite, because it
|
||||||
# takes too long
|
# takes too long
|
||||||
|
129
tests/gpg/t-thread-keylist-verify.c
Normal file
129
tests/gpg/t-thread-keylist-verify.c
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/* t-thread-verify.c - Regression test.
|
||||||
|
Copyright (C) 2015 Intevation GmbH
|
||||||
|
|
||||||
|
This file is part of GPGME.
|
||||||
|
|
||||||
|
GPGME is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2.1 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
GPGME is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
02111-1307, USA. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <gpgme.h>
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "t-support.h"
|
||||||
|
|
||||||
|
#define THREAD_COUNT 500
|
||||||
|
|
||||||
|
static const char test_text1[] = "Just GNU it!\n";
|
||||||
|
static const char test_sig1[] =
|
||||||
|
"-----BEGIN PGP SIGNATURE-----\n"
|
||||||
|
"\n"
|
||||||
|
"iN0EABECAJ0FAjoS+i9FFIAAAAAAAwA5YmFyw7bDpMO8w58gZGFzIHdhcmVuIFVt\n"
|
||||||
|
"bGF1dGUgdW5kIGpldHp0IGVpbiBwcm96ZW50JS1aZWljaGVuNRSAAAAAAAgAJGZv\n"
|
||||||
|
"b2Jhci4xdGhpcyBpcyBhIG5vdGF0aW9uIGRhdGEgd2l0aCAyIGxpbmVzGhpodHRw\n"
|
||||||
|
"Oi8vd3d3Lmd1Lm9yZy9wb2xpY3kvAAoJEC1yfMdoaXc0JBIAoIiLlUsvpMDOyGEc\n"
|
||||||
|
"dADGKXF/Hcb+AKCJWPphZCphduxSvrzH0hgzHdeQaA==\n"
|
||||||
|
"=nts1\n"
|
||||||
|
"-----END PGP SIGNATURE-----\n";
|
||||||
|
|
||||||
|
void *
|
||||||
|
start_keylist (void *arg)
|
||||||
|
{
|
||||||
|
gpgme_error_t err;
|
||||||
|
gpgme_ctx_t ctx;
|
||||||
|
gpgme_key_t key;
|
||||||
|
|
||||||
|
err = gpgme_new (&ctx);
|
||||||
|
fail_if_err (err);
|
||||||
|
|
||||||
|
err = gpgme_op_keylist_start (ctx, NULL, 0);
|
||||||
|
fail_if_err (err);
|
||||||
|
|
||||||
|
while (!(err = gpgme_op_keylist_next (ctx, &key)));
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
start_verify (void *arg)
|
||||||
|
{
|
||||||
|
gpgme_ctx_t ctx;
|
||||||
|
gpgme_error_t err;
|
||||||
|
gpgme_data_t sig, text;
|
||||||
|
gpgme_verify_result_t result;
|
||||||
|
gpgme_signature_t signature;
|
||||||
|
|
||||||
|
err = gpgme_new (&ctx);
|
||||||
|
fail_if_err (err);
|
||||||
|
|
||||||
|
/* Checking a valid message. */
|
||||||
|
err = gpgme_data_new_from_mem (&text, test_text1, strlen (test_text1), 0);
|
||||||
|
fail_if_err (err);
|
||||||
|
err = gpgme_data_new_from_mem (&sig, test_sig1, strlen (test_sig1), 0);
|
||||||
|
fail_if_err (err);
|
||||||
|
err = gpgme_op_verify (ctx, sig, text, NULL);
|
||||||
|
fail_if_err (err);
|
||||||
|
result = gpgme_op_verify_result (ctx);
|
||||||
|
|
||||||
|
signature = result->signatures;
|
||||||
|
|
||||||
|
if (strcmp (signature->fpr, "A0FF4590BB6122EDEF6E3C542D727CC768697734"))
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s:%i: Unexpected fingerprint: %s\n",
|
||||||
|
__FILE__, __LINE__, signature->fpr);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
if (gpgme_err_code (signature->status) != GPG_ERR_NO_ERROR)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s:%i: Unexpected signature status: %s\n",
|
||||||
|
__FILE__, __LINE__, gpgme_strerror (signature->status));
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
pthread_t verify_threads[THREAD_COUNT];
|
||||||
|
pthread_t keylist_threads[THREAD_COUNT];
|
||||||
|
init_gpgme (GPGME_PROTOCOL_OpenPGP);
|
||||||
|
|
||||||
|
for (i = 0; i < THREAD_COUNT; i++)
|
||||||
|
{
|
||||||
|
if (pthread_create(&verify_threads[i], NULL, start_verify, NULL) ||
|
||||||
|
pthread_create(&keylist_threads[i], NULL, start_keylist, NULL))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s:%i: failed to create threads \n",
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < THREAD_COUNT; i++)
|
||||||
|
{
|
||||||
|
pthread_join (verify_threads[i], NULL);
|
||||||
|
pthread_join (keylist_threads[i], NULL);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
76
tests/gpg/t-thread-keylist.c
Normal file
76
tests/gpg/t-thread-keylist.c
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/* t-thread-verify.c - Regression test.
|
||||||
|
Copyright (C) 2015 Intevation GmbH
|
||||||
|
|
||||||
|
This file is part of GPGME.
|
||||||
|
|
||||||
|
GPGME is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2.1 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
GPGME is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
02111-1307, USA. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <gpgme.h>
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "t-support.h"
|
||||||
|
|
||||||
|
#define THREAD_COUNT 500
|
||||||
|
|
||||||
|
void *
|
||||||
|
start_keylist (void *arg)
|
||||||
|
{
|
||||||
|
gpgme_error_t err;
|
||||||
|
gpgme_ctx_t ctx;
|
||||||
|
gpgme_key_t key;
|
||||||
|
|
||||||
|
err = gpgme_new (&ctx);
|
||||||
|
fail_if_err (err);
|
||||||
|
|
||||||
|
err = gpgme_op_keylist_start (ctx, NULL, 0);
|
||||||
|
fail_if_err (err);
|
||||||
|
|
||||||
|
while (!(err = gpgme_op_keylist_next (ctx, &key)));
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
pthread_t keylist_threads[THREAD_COUNT];
|
||||||
|
init_gpgme (GPGME_PROTOCOL_OpenPGP);
|
||||||
|
|
||||||
|
for (i = 0; i < THREAD_COUNT; i++)
|
||||||
|
{
|
||||||
|
if (pthread_create(&keylist_threads[i], NULL, start_keylist, NULL))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s:%i: failed to create threads \n",
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < THREAD_COUNT; i++)
|
||||||
|
{
|
||||||
|
pthread_join (keylist_threads[i], NULL);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user