summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2019-06-12 10:49:34 +0200
committerWerner Koch <wk@gnupg.org>2019-06-12 10:50:30 +0200
commit5cfdf878fbc60328bbbc0b0c302a85dea679ad81 (patch)
tree9c88686ca483e455907edbdff300135fa29f843d
parent92883efe7176c2022e25e913c1d2f40c35a0754a (diff)
downloadgpgme-5cfdf878fbc60328bbbc0b0c302a85dea679ad81.tar.gz
core: Link all context objects and add _gpgme_get_ctx.
* src/context.h (struct gpgme_context): Add field 'next_ctx'. * src/gpgme.c (def_lc_lock): Replace by ... (context_list_lock): new. (context_list): New variable. (gpgme_new): Add new context object to the list. (gpgme_release): Remove context object from the list. (_gpgme_get_ctx): New function. -- To allow mapping a context serial number back to a context object and to check whether a serialno has still a context object, we need to link them all together. We already take a lock to setup the locale and thus the only overhead is in freeing the context. Signed-off-by: Werner Koch <wk@gnupg.org>
-rw-r--r--src/context.h16
-rw-r--r--src/gpgme.c89
-rw-r--r--src/ops.h3
3 files changed, 91 insertions, 17 deletions
diff --git a/src/context.h b/src/context.h
index 076d0731..7333d2d5 100644
--- a/src/context.h
+++ b/src/context.h
@@ -73,9 +73,10 @@ struct ctx_op_data
};
typedef struct ctx_op_data *ctx_op_data_t;
+
/* The context defines an environment in which crypto operations can
- be performed (sequentially). */
+ * be performed (sequentially). */
struct gpgme_context
{
DECLARE_LOCK (lock);
@@ -86,6 +87,11 @@ struct gpgme_context
* freed and reused. */
uint64_t serial;
+ /* A link to the next context. We keep all contex object in the
+ * linked list to so that we are abale to find a context by its
+ * serial number. */
+ gpgme_ctx_t next_ctx;
+
/* True if the context was canceled asynchronously. */
int canceled;
@@ -198,5 +204,13 @@ struct gpgme_context
/* Macro to retrieve the serial number. Returns 0 if CTX is NULL. */
#define CTXSERIAL(ctx) (ctx? (unsigned long)ctx->serial : 0)
+/*-- gpgme.c --*/
+
+gpg_error_t _gpgme_get_ctx (uint64_t serial, gpgme_ctx_t *r_ctx);
+
+gpgme_error_t _gpgme_cancel_with_err (gpgme_ctx_t ctx, gpg_error_t ctx_err,
+ gpg_error_t op_err);
+
+
#endif /* CONTEXT_H */
diff --git a/src/gpgme.c b/src/gpgme.c
index 53189aa7..283290f4 100644
--- a/src/gpgme.c
+++ b/src/gpgme.c
@@ -1,7 +1,7 @@
/* gpgme.c - GnuPG Made Easy.
* Copyright (C) 2000 Werner Koch (dd9jn)
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2012,
- * 2014, 2015 g10 Code GmbH
+ * 2014, 2015, 2019 g10 Code GmbH
*
* This file is part of GPGME.
*
@@ -42,26 +42,32 @@
#include "mbox-util.h"
-/* The default locale and its lock. This lock is also used for the
- * context serial number. */
-DEFINE_STATIC_LOCK (def_lc_lock);
+/* The lock used to protect access to the default locale, the global
+ * serial counter, and the list of context objects. */
+DEFINE_STATIC_LOCK (context_list_lock);
+
+/* The default locale. Access is protected by CONTEXT_LIST_LOCK. */
static char *def_lc_ctype;
static char *def_lc_messages;
/* A serial number to identify a context. To make debugging easier by
* distinguishing this from the data object s/n we initialize it with
* an arbitrary offset. Debug output of this should be done using
- * decimal notation. Updates are protected by the DEF_LC_LOCK. */
+ * decimal notation. Updates are protected by CONTEXT_LIST_LOCK. */
static uint64_t last_ctx_serial = 200000;
+/* A linked list of all context objects. Protected by
+ * CONTEXT_LIST_LOCK. */
+static gpgme_ctx_t context_list;
-
gpgme_error_t _gpgme_selftest = GPG_ERR_NOT_OPERATIONAL;
/* Protects all reference counters in result structures. All other
- accesses to a result structure are read only. */
+ * accesses to a result structure are read only. */
DEFINE_STATIC_LOCK (result_ref_lock);
+
+
/* Set the global flag NAME to VALUE. Return 0 on success. Note that
this function does not use gpgme_error and thus a non-zero return
@@ -131,14 +137,14 @@ gpgme_new (gpgme_ctx_t *r_ctx)
ctx->sub_protocol = GPGME_PROTOCOL_DEFAULT;
_gpgme_fd_table_init (&ctx->fdt);
- LOCK (def_lc_lock);
+ LOCK (context_list_lock);
if (def_lc_ctype)
{
ctx->lc_ctype = strdup (def_lc_ctype);
if (!ctx->lc_ctype)
{
int saved_err = gpg_error_from_syserror ();
- UNLOCK (def_lc_lock);
+ UNLOCK (context_list_lock);
_gpgme_engine_info_release (ctx->engine_info);
free (ctx);
return TRACE_ERR (saved_err);
@@ -153,7 +159,7 @@ gpgme_new (gpgme_ctx_t *r_ctx)
if (!ctx->lc_messages)
{
int saved_err = gpg_error_from_syserror ();
- UNLOCK (def_lc_lock);
+ UNLOCK (context_list_lock);
if (ctx->lc_ctype)
free (ctx->lc_ctype);
_gpgme_engine_info_release (ctx->engine_info);
@@ -166,7 +172,11 @@ gpgme_new (gpgme_ctx_t *r_ctx)
ctx->serial = ++last_ctx_serial;
- UNLOCK (def_lc_lock);
+ /* Put the object itno a list. */
+ ctx->next_ctx = context_list;
+ context_list = ctx;
+
+ UNLOCK (context_list_lock);
*r_ctx = ctx;
@@ -175,6 +185,39 @@ gpgme_new (gpgme_ctx_t *r_ctx)
}
+/* Check the status of the context described by SERIAL.
+ * Returns:
+ * 0 - All fine
+ * GPG_ERR_CANCELED - Context operation has been canceled.
+ * GPG_ERR_NO_OBJ - Context ist not anymore known.
+ * If R_CTX is not NULl and the context exists, it is stored there.
+ */
+gpg_error_t
+_gpgme_get_ctx (uint64_t serial, gpgme_ctx_t *r_ctx)
+{
+ gpg_error_t err;
+ gpgme_ctx_t ctx = NULL;
+
+ LOCK (context_list_lock);
+ for (ctx = context_list; ctx; ctx = ctx->next_ctx)
+ if (ctx->serial == serial)
+ break;
+ UNLOCK (context_list_lock);
+ if (ctx)
+ {
+ /* FIXME: The lock is only used for the canceled flag. We
+ * should remove it and rely on the global
+ * context_list_lock. */
+ LOCK (ctx->lock);
+ err = ctx->canceled? gpg_error (GPG_ERR_CANCELED) : 0;
+ UNLOCK (ctx->lock);
+ }
+ else
+ err = gpg_error (GPG_ERR_NO_OBJ);
+ if (r_ctx)
+ *r_ctx = ctx;
+ return err;
+}
gpgme_error_t
_gpgme_cancel_with_err (gpgme_ctx_t ctx, gpg_error_t ctx_err,
gpg_error_t op_err)
@@ -252,6 +295,26 @@ gpgme_release (gpgme_ctx_t ctx)
if (!ctx)
return;
+ LOCK (context_list_lock);
+ if (context_list == ctx)
+ {
+ context_list = ctx->next_ctx;
+ ctx->next_ctx = NULL;
+ }
+ else
+ {
+ gpgme_ctx_t tmpctx;
+
+ for (tmpctx = context_list; tmpctx; tmpctx = tmpctx->next_ctx)
+ if (tmpctx->next_ctx == ctx)
+ {
+ tmpctx->next_ctx = ctx->next_ctx;
+ ctx->next_ctx = NULL;
+ break;
+ }
+ }
+ UNLOCK (context_list_lock);
+
_gpgme_engine_release (ctx->engine);
ctx->engine = NULL;
_gpgme_fd_table_deinit (&ctx->fdt);
@@ -1054,7 +1117,7 @@ gpgme_set_locale (gpgme_ctx_t ctx, int category, const char *value)
}
if (!ctx)
- LOCK (def_lc_lock);
+ LOCK (context_list_lock);
#ifdef LC_CTYPE
SET_ONE_LOCALE (ctype, CTYPE);
#endif
@@ -1062,7 +1125,7 @@ gpgme_set_locale (gpgme_ctx_t ctx, int category, const char *value)
SET_ONE_LOCALE (messages, MESSAGES);
#endif
if (!ctx)
- UNLOCK (def_lc_lock);
+ UNLOCK (context_list_lock);
return TRACE_ERR (0);
}
diff --git a/src/ops.h b/src/ops.h
index 3b9728dd..013b2cd2 100644
--- a/src/ops.h
+++ b/src/ops.h
@@ -26,9 +26,6 @@
#include "context.h"
-/* From gpgme.c. */
-gpgme_error_t _gpgme_cancel_with_err (gpgme_ctx_t ctx, gpg_error_t ctx_err,
- gpg_error_t op_err);
/* Clear all notation data from the context. */
void _gpgme_sig_notation_clear (gpgme_ctx_t ctx);