diff options
| author | Marcus Brinkmann <[email protected]> | 2008-06-27 16:07:33 +0000 | 
|---|---|---|
| committer | Marcus Brinkmann <[email protected]> | 2008-06-27 16:07:33 +0000 | 
| commit | 695ec56ffbf3cf1cb4722f5fab33dd2bdb43a9af (patch) | |
| tree | 0292c4e761d3ee380634ac961e687b4d75777377 | |
| parent | Fix incompatibility with non-recent mingw runtimes. (diff) | |
| download | gpgme-695ec56ffbf3cf1cb4722f5fab33dd2bdb43a9af.tar.gz gpgme-695ec56ffbf3cf1cb4722f5fab33dd2bdb43a9af.zip | |
2008-06-27  Marcus Brinkmann  <[email protected]>
	* gpgme.texi (Cancellation): Document gpgme_cancel_async.
gpgme/
2008-06-27  Marcus Brinkmann  <[email protected]>
	* context.h: Include "sema.h".
	(struct gpgme_context): New members lock and canceled.
	* gpgme.c (gpgme_new): Initialize lock.
	(gpgme_release): Destroy lock.
	(gpgme_cancel_async): New function.
	* op-support.c (_gpgme_op_reset): Reset the canceled flag.
	* wait-global.c (gpgme_wait): Check cancel flag before processing
	any I/O callbacks.
	* wait-private.c (_gpgme_wait_on_condition): Likewise.
	* wait-user.c (_gpgme_user_io_cb_handler): Likewise.
Diffstat (limited to '')
| -rw-r--r-- | doc/ChangeLog | 4 | ||||
| -rw-r--r-- | doc/gpgme.texi | 28 | ||||
| -rw-r--r-- | gpgme/ChangeLog | 13 | ||||
| -rw-r--r-- | gpgme/context.h | 6 | ||||
| -rw-r--r-- | gpgme/gpgme.c | 19 | ||||
| -rw-r--r-- | gpgme/gpgme.h | 3 | ||||
| -rw-r--r-- | gpgme/op-support.c | 3 | ||||
| -rw-r--r-- | gpgme/wait-global.c | 10 | ||||
| -rw-r--r-- | gpgme/wait-private.c | 8 | ||||
| -rw-r--r-- | gpgme/wait-user.c | 10 | 
10 files changed, 92 insertions, 12 deletions
| diff --git a/doc/ChangeLog b/doc/ChangeLog index a6adbdb6..8f5502a7 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2008-06-27  Marcus Brinkmann  <[email protected]> + +	* gpgme.texi (Cancellation): Document gpgme_cancel_async. +  2008-06-25  Werner Koch  <[email protected]>  	* gpgme.texi (Listing Keys): Updated example to the current API. diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 2b96d873..50b82e23 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -5488,13 +5488,15 @@ private:  @cindex aborting operations  @cindex cancelling operations -Sometimes you do not want to wait for an operation to finish.  If you -use external I/O callbacks, you can cancel a pending operation. -However, you must ensure that no other thread is currently using the -context in which the operation you want to cancel runs.  This includes -callback handlers.  So your external event loop must either be halted -or otherwise it must be guaranteed that no installed I/O callbacks are -run for this context. +Sometimes you do not want to wait for an operation to finish. +@acronym{GPGME} provides two different functions to achieve that.  The +function @code{gpgme_cancel} takes effect immediately.  When it +returns, the operation is effectively canceled.  However, it has some +limitations and can not be used with synchronous operations.  In +contrast, the function @code{gpgme_cancel_async} can be used with any +context and from any thread, but it is not guaranteed to take effect +immediately.  Instead, cancellation occurs at the next possible time +(typically the next time I/O occurs in the target context).  @deftypefun gpgme_ctx_t gpgme_cancel (@w{gpgme_ctx_t @var{ctx}})  The function @code{gpgme_cancel} attempts to cancel a pending @@ -5517,6 +5519,18 @@ The function returns an error code if the cancellation failed (in this  case the state of @var{ctx} is not modified).  @end deftypefun + +@deftypefun gpgme_ctx_t gpgme_cancel_async (@w{gpgme_ctx_t @var{ctx}}) +The function @code{gpgme_cancel} attempts to cancel a pending +operation in the context @var{ctx}.  This can be called by any thread +at any time after starting an operation on the context, but will not +take effect immediately.  The actual cancellation happens at the next +time GPGME processes I/O in that context. + +The function returns an error code if the cancellation failed (in this +case the state of @var{ctx} is not modified). +@end deftypefun +  @c **********************************************************  @c *******************  Appendices  *************************  @c ********************************************************** diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index cdda77ca..198f5f77 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,16 @@ +2008-06-27  Marcus Brinkmann  <[email protected]> + +	* context.h: Include "sema.h". +	(struct gpgme_context): New members lock and canceled. +	* gpgme.c (gpgme_new): Initialize lock. +	(gpgme_release): Destroy lock. +	(gpgme_cancel_async): New function. +	* op-support.c (_gpgme_op_reset): Reset the canceled flag. +	* wait-global.c (gpgme_wait): Check cancel flag before processing +	any I/O callbacks. +	* wait-private.c (_gpgme_wait_on_condition): Likewise. +	* wait-user.c (_gpgme_user_io_cb_handler): Likewise. +  2008-06-26  Werner Koch  <[email protected]>  	* w32-util.c (_gpgme_mkstemp): Replace sprint by stpcpy. diff --git a/gpgme/context.h b/gpgme/context.h index e7e2afa4..ed5d8502 100644 --- a/gpgme/context.h +++ b/gpgme/context.h @@ -25,6 +25,7 @@  #include "gpgme.h"  #include "engine.h"  #include "wait.h" +#include "sema.h"  /* Operations might require to remember arbitrary information and data @@ -63,6 +64,11 @@ typedef struct ctx_op_data *ctx_op_data_t;     be performed (sequentially).  */  struct gpgme_context  { +  DECLARE_LOCK (lock); + +  /* True if the context was canceled asynchronously.  */ +  int canceled; +    /* The engine info for this context.  */    gpgme_engine_info_t engine_info; diff --git a/gpgme/gpgme.c b/gpgme/gpgme.c index a96db530..0f3527a4 100644 --- a/gpgme/gpgme.c +++ b/gpgme/gpgme.c @@ -54,6 +54,8 @@ gpgme_new (gpgme_ctx_t *r_ctx)    if (!ctx)      return TRACE_ERR (gpg_error_from_errno (errno)); +  INIT_LOCK (ctx->lock); +      _gpgme_engine_info_copy (&ctx->engine_info);    if (!ctx->engine_info)      { @@ -121,6 +123,22 @@ gpgme_cancel (gpgme_ctx_t ctx)    return TRACE_ERR (0);  } + +/* Cancel a pending operation asynchronously.  */ +gpgme_error_t +gpgme_cancel_async (gpgme_ctx_t ctx) +{ +  gpgme_error_t err; +  TRACE_BEG (DEBUG_CTX, "gpgme_cancel_async", ctx); + +  LOCK (ctx->lock); +  ctx->canceled = 1; +  UNLOCK (ctx->lock); + +  return TRACE_ERR (0); +} + +  /* Release all resources associated with the given context.  */  void  gpgme_release (gpgme_ctx_t ctx) @@ -139,6 +157,7 @@ gpgme_release (gpgme_ctx_t ctx)    if (ctx->lc_messages)      free (ctx->lc_messages);    _gpgme_engine_info_release (ctx->engine_info); +  DESTROY_LOCK (ctx->lock);    free (ctx);  } diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index 8740469f..569752fd 100644 --- a/gpgme/gpgme.h +++ b/gpgme/gpgme.h @@ -1120,6 +1120,9 @@ unsigned long gpgme_key_sig_get_ulong_attr (gpgme_key_t key, int uid_idx,  /* Cancel a pending asynchronous operation.  */  gpgme_error_t gpgme_cancel (gpgme_ctx_t ctx); +/* Cancel a pending operation asynchronously.  */ +gpgme_error_t gpgme_cancel_async (gpgme_ctx_t ctx); +  struct _gpgme_invalid_key  { diff --git a/gpgme/op-support.c b/gpgme/op-support.c index 1212c542..fefccc67 100644 --- a/gpgme/op-support.c +++ b/gpgme/op-support.c @@ -76,6 +76,9 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type)    type &= 255;    _gpgme_release_result (ctx); +  LOCK (ctx->lock); +  ctx->canceled = 0; +  UNLOCK (ctx->lock);    if (ctx->engine && no_reset)      reuse_engine = 1; diff --git a/gpgme/wait-global.c b/gpgme/wait-global.c index 3b1e3d9a..97ece499 100644 --- a/gpgme/wait-global.c +++ b/gpgme/wait-global.c @@ -299,7 +299,7 @@ gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang)  	  if (fdt.fds[i].fd != -1 && fdt.fds[i].signaled)  	    {  	      gpgme_ctx_t ictx; -	      gpgme_error_t err; +	      gpgme_error_t err = 0;  	      struct wait_item_s *item;  	      assert (nr); @@ -310,7 +310,13 @@ gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang)  	      ictx = item->ctx;  	      assert (ictx); -	      err = _gpgme_run_io_cb (&fdt.fds[i], 0); +	      LOCK (ctx->lock); +	      if (ctx->canceled) +		err = gpg_error (GPG_ERR_CANCELED); +	      UNLOCK (ctx->lock); + +	      if (!err) +		err = _gpgme_run_io_cb (&fdt.fds[i], 0);  	      if (err)  		{  		  /* An error occured.  Close all fds in this context, diff --git a/gpgme/wait-private.c b/gpgme/wait-private.c index 73f11b76..6633cf67 100644 --- a/gpgme/wait-private.c +++ b/gpgme/wait-private.c @@ -105,7 +105,13 @@ _gpgme_wait_on_condition (gpgme_ctx_t ctx, volatile int *cond)  	      assert (nr);  	      nr--; -	      err = _gpgme_run_io_cb (&ctx->fdt.fds[i], 0); +	      LOCK (ctx->lock); +	      if (ctx->canceled) +		err = gpg_error (GPG_ERR_CANCELED); +	      UNLOCK (ctx->lock); +	       +	      if (!err) +		err = _gpgme_run_io_cb (&ctx->fdt.fds[i], 0);  	      if (err)  		{  		  /* An error occured.  Close all fds in this context, diff --git a/gpgme/wait-user.c b/gpgme/wait-user.c index 605401e9..7fd61a9b 100644 --- a/gpgme/wait-user.c +++ b/gpgme/wait-user.c @@ -39,7 +39,7 @@  gpgme_error_t  _gpgme_user_io_cb_handler (void *data, int fd)  { -  gpgme_error_t err; +  gpgme_error_t err = 0;    struct tag *tag = (struct tag *) data;    gpgme_ctx_t ctx; @@ -47,7 +47,13 @@ _gpgme_user_io_cb_handler (void *data, int fd)    ctx = tag->ctx;    assert (ctx); -  err = _gpgme_run_io_cb (&ctx->fdt.fds[tag->idx], 0); +  LOCK (ctx->lock); +  if (ctx->canceled) +    err = gpg_error (GPG_ERR_CANCELED); +  UNLOCK (ctx->lock); + +  if (! err) +    err = _gpgme_run_io_cb (&ctx->fdt.fds[tag->idx], 0);    if (err)      {        unsigned int idx; | 
