From: Marcus Brinkmann Date: Thu, 2 Jun 2005 21:59:34 +0000 (+0000) Subject: 2005-06-02 Marcus Brinkmann X-Git-Tag: gpgme-1-1-0~37 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=7ccc3083305c8c116a5be85601e27ceed37947d9;p=gpgme.git 2005-06-02 Marcus Brinkmann * wait.h (_gpgme_run_io_cb): New prototype. * wait.c (_gpgme_run_io_cb): New function. * wait-global.c (gpgme_wait): Call it. * wait-user.c (_gpgme_user_io_cb_handler): Likewise. * wait-private.c (_gpgme_wait_on_condition): Likewise. --- diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 0a2509d..82f5fd6 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,11 @@ +2005-06-02 Marcus Brinkmann + + * wait.h (_gpgme_run_io_cb): New prototype. + * wait.c (_gpgme_run_io_cb): New function. + * wait-global.c (gpgme_wait): Call it. + * wait-user.c (_gpgme_user_io_cb_handler): Likewise. + * wait-private.c (_gpgme_wait_on_condition): Likewise. + 2005-06-02 Werner Koch * passphrase.c (_gpgme_passphrase_status_handler): Take care of diff --git a/gpgme/wait-global.c b/gpgme/wait-global.c index db422bf..d9f8727 100644 --- a/gpgme/wait-global.c +++ b/gpgme/wait-global.c @@ -310,7 +310,7 @@ gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang) ictx = item->ctx; assert (ictx); - err = item->handler (item->handler_value, fdt.fds[i].fd); + 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 f883f20..73f11b7 100644 --- a/gpgme/wait-private.c +++ b/gpgme/wait-private.c @@ -101,15 +101,11 @@ _gpgme_wait_on_condition (gpgme_ctx_t ctx, volatile int *cond) { if (ctx->fdt.fds[i].fd != -1 && ctx->fdt.fds[i].signaled) { - struct wait_item_s *item; - ctx->fdt.fds[i].signaled = 0; assert (nr); nr--; - - item = (struct wait_item_s *) ctx->fdt.fds[i].opaque; - err = item->handler (item->handler_value, ctx->fdt.fds[i].fd); + 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 0f046f2..605401e 100644 --- a/gpgme/wait-user.c +++ b/gpgme/wait-user.c @@ -42,15 +42,12 @@ _gpgme_user_io_cb_handler (void *data, int fd) gpgme_error_t err; struct tag *tag = (struct tag *) data; gpgme_ctx_t ctx; - struct wait_item_s *item; assert (data); ctx = tag->ctx; assert (ctx); - item = (struct wait_item_s *) ctx->fdt.fds[tag->idx].opaque; - assert (item); - err = (*item->handler) (item->handler_value, fd); + err = _gpgme_run_io_cb (&ctx->fdt.fds[tag->idx], 0); if (err) { unsigned int idx; diff --git a/gpgme/wait.c b/gpgme/wait.c index 4d3cbf8..16a9f23 100644 --- a/gpgme/wait.c +++ b/gpgme/wait.c @@ -167,3 +167,38 @@ _gpgme_remove_io_cb (void *data) fdt->fds[idx].for_write = 0; fdt->fds[idx].opaque = NULL; } + + +/* This is slightly embarrassing. The problem is that running an I/O + callback _may_ influence the status of other file descriptors. Our + own event loops could compensate for that, but the external event + loops cannot. FIXME: We may still want to optimize this a bit when + we are called from our own event loops. So if CHECKED is 1, the + check is skipped. */ +gpgme_error_t +_gpgme_run_io_cb (struct io_select_fd_s *an_fds, int checked) +{ + struct wait_item_s *item; + item = (struct wait_item_s *) an_fds->opaque; + assert (item); + + if (!checked) + { + int nr; + struct io_select_fd_s fds; + + fds = *an_fds; + fds.signaled = 0; + /* Just give it a quick poll. */ + nr = _gpgme_io_select (&fds, 1, 1); + assert (nr <= 1); + if (nr < 0) + return errno; + else if (nr == 0) + /* The status changed in the meantime, there is nothing left + to do. */ + return 0; + } + + return item->handler (item->handler_value, an_fds->fd); +} diff --git a/gpgme/wait.h b/gpgme/wait.h index cec4d8d..eafbb6f 100644 --- a/gpgme/wait.h +++ b/gpgme/wait.h @@ -77,4 +77,6 @@ void _gpgme_wait_user_event_cb (void *data, gpgme_event_io_t type, gpgme_error_t _gpgme_wait_one (gpgme_ctx_t ctx); +gpgme_error_t _gpgme_run_io_cb (struct io_select_fd_s *an_fds, int checked); + #endif /* WAIT_H */