needed. Still, it is there if necessary. If in doubt, contact us
and we will give our advise for your specific situation.
- * A new key listing mode for validation of the key has been added.
- See the manual.
+ * New key listing mode GPGME_KEYLIST_MODE_VALIDATE for validation of
+ the listed keys.
+
+ * New interface gpgme_cancel() that can be used to cancel
+ asynchronous operations.
* Interface changes relative to the 0.4.4 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gpgme_data_seek_cb_t CHANGED: off_t is now a largefile type.
gpgme_data_seek CHANGED: off_t is now a largefile type.
gpgme_data_new_from_filepart CHANGED: off_t is now a largefile type.
-GPGME_KEYLIST_MODE_VALIDATE NEW.
-
+GPGME_KEYLIST_MODE_VALIDATE NEW
+gpgme_cancel NEW
Noteworthy changes in version 0.4.4 (2004-01-12)
------------------------------------------------
+2004-02-24 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.texi (cancellation): New section.
+
2004-02-17 Werner Koch <wk@gnupg.org>
* gpgme.texi (Key Listing Mode): Doc KEYLIST_MODE_VALIDATE.
* Waiting For Completion:: Waiting until an operation is completed.
* Using External Event Loops:: Advanced control over what happens when.
+* Cancellation:: How to end pending operations prematurely.
Using External Event Loops
@menu
* Waiting For Completion:: Waiting until an operation is completed.
* Using External Event Loops:: Advanced control over what happens when.
+* Cancellation:: How to end pending operations prematurely.
@end menu
@end example
+@node Cancellation
+@subsection Cancellation
+@cindex cryptographic operation, aborting
+@cindex cryptographic operation, cancelling
+@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.
+
+@deftypefun gpgme_ctx_t gpgme_cancel (@w{gpgme_ctx_t @var{ctx}})
+The function @code{gpgme_cancel} attempts to cancel a pending
+operation in the context @var{ctx}. This only works if you use the
+global event loop or your own event loop.
+
+If you use the global event loop, you must not call @code{gpgme_wait}
+or @code{gpgme_wait} during cancellation. After successful
+cancellation, you can call @code{gpgme_wait} (optionally waiting on
+@var{ctx}), and the context @var{ctx} will appear as if it had
+finished with the error code @code{GPG_ERR_CANCEL}.
+
+If you use your an external event loop, you must ensure that no I/O
+callbacks are invoked for this context (for example by halting the
+event loop). On successful cancellation, all registered I/O callbacks
+for this context will be unregistered, and a @code{GPGME_EVENT_DONE}
+event with the error code @code{GPG_ERR_CANCEL} will be signaled.
+
+The function returns an error code if the cancellation failed (in this
+case the state of @var{ctx} is not modified).
+@end deftypefun
+
+
@include gpl.texi
+2004-02-24 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.c (gpgme_cancel): New function.
+ * engine-backend.h (struct engine_ops): New member cancel.
+ * engine.h (_gpgme_engine_cancel): New prototype.
+ * engine.c (_gpgme_engine_cancel): New function.
+ * engine-gpgsm.c: Add new member cancel.
+ (gpgsm_cancel): New function.
+ (gpgsm_release): Use it.
+ * rungpg.c: Add new member cancel.
+
2004-02-17 Werner Koch <wk@gnupg.org>
* gpgme.h: Add GPGME_KEYLIST_MODE_VALIDATE.
void (*set_io_cbs) (void *engine, gpgme_io_cbs_t io_cbs);
void (*io_event) (void *engine, gpgme_event_io_t type, void *type_data);
+
+ gpgme_error_t (*cancel) (void *engine);
};
}
-static void
-gpgsm_release (void *engine)
+static gpgme_error_t
+gpgsm_cancel (void *engine)
{
engine_gpgsm_t gpgsm = engine;
_gpgme_io_close (gpgsm->message_cb.fd);
assuan_disconnect (gpgsm->assuan_ctx);
+}
+
+
+static void
+gpgsm_release (void *engine)
+{
+ engine_gpgsm_t gpgsm = engine;
+
+ if (!gpgsm)
+ return;
+
+ gpgsm_cancel (engine);
free (gpgsm->colon.attic.line);
free (gpgsm);
NULL, /* trustlist */
gpgsm_verify,
gpgsm_set_io_cbs,
- gpgsm_io_event
+ gpgsm_io_event,
+ gpgsm_cancel
};
(*engine->ops->io_event) (engine->engine, type, type_data);
}
+
+
+gpgme_error_t
+_gpgme_engine_cancel (engine_t engine)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->cancel)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->cancel) (engine->engine);
+}
void _gpgme_engine_io_event (engine_t engine,
gpgme_event_io_t type, void *type_data);
+gpgme_error_t _gpgme_engine_cancel (engine_t engine);
+
#endif /* ENGINE_H */
}
+/* Cancel a pending asynchronous operation. */
+gpgme_error_t
+gpgme_cancel (gpgme_ctx_t ctx)
+{
+ gpgme_error_t err;
+
+ err = _gpgme_engine_cancel (ctx->engine);
+ if (err)
+ return err;
+
+ err = gpg_error (GPG_ERR_CANCELED);
+ _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &err);
+
+ return 0;
+}
+
/* Release all resources associated with the given context. */
void
gpgme_release (gpgme_ctx_t ctx)
\f
/* Crypto Operations. */
+/* Cancel a pending asynchronous operation. */
+gpgme_error_t gpgme_cancel (gpgme_ctx_t ctx);
+
+\f
struct _gpgme_invalid_key
{
struct _gpgme_invalid_key *next;
gpg_trustlist,
gpg_verify,
gpg_set_io_cbs,
- gpg_io_event
+ gpg_io_event,
+ NULL
};