core: Make the refactored global wait work.
* src/fdtable.h (FDTABLE_FLAG_NOT_DONE): New flag. * src/fdtable.c (_gpgme_fdtable_io_cb_count): Rename to ... (_gpgme_fdtable_get_count): this and add arg 'flags'. (_gpgme_fdtable_run_io_cbs): Add return arg 'r_owner'. * src/wait.c (gpgme_wait_ext): Improve tracing. Act upon error codes from running the callbacks. * tests/gpg/t-wait.c (main): Remove the sleep. -- Now t-wait works again. There are still problems with the user defined events but it is another step in our refactoring work. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
153f1128f8
commit
0378250846
@ -417,7 +417,7 @@ _gpgme_fdtable_remove (int fd)
|
|||||||
handlervalue = fdtable[idx].close_notify.value;
|
handlervalue = fdtable[idx].close_notify.value;
|
||||||
fdtable[idx].close_notify.value = NULL;
|
fdtable[idx].close_notify.value = NULL;
|
||||||
|
|
||||||
/* The handler might call into the fdtable again, so of we have a
|
/* The handler might call into the fdtable again, so if we have a
|
||||||
* handler we can't immediately close it but instead record the fact
|
* handler we can't immediately close it but instead record the fact
|
||||||
* and remove the entry from the table only after the handler has
|
* and remove the entry from the table only after the handler has
|
||||||
* been run. */
|
* been run. */
|
||||||
@ -445,10 +445,15 @@ _gpgme_fdtable_remove (int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Return the number of active I/O callbacks for OWNER or for all if
|
/* Return the number of FDs for OWNER (or for all if OWNER is 0)
|
||||||
* OWNER is 0. */
|
* which match FLAGS. Recognized flag values are:
|
||||||
|
* 0 - Number FDs with IO callbacks
|
||||||
|
* FDTABLE_FLAG_ACTIVE - Number of FDs in the active state.
|
||||||
|
* FDTABLE_FLAG_DONE - Number of FDs in the done state.
|
||||||
|
* FDTABLE_FLAG_NOT_DONE - Number of FDs not in the done state.
|
||||||
|
*/
|
||||||
unsigned int
|
unsigned int
|
||||||
_gpgme_fdtable_io_cb_count (uint64_t owner)
|
_gpgme_fdtable_get_count (uint64_t owner, unsigned int flags)
|
||||||
{
|
{
|
||||||
int idx;
|
int idx;
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
@ -456,11 +461,23 @@ _gpgme_fdtable_io_cb_count (uint64_t owner)
|
|||||||
LOCK (fdtable_lock);
|
LOCK (fdtable_lock);
|
||||||
for (idx=0; idx < fdtablesize; idx++)
|
for (idx=0; idx < fdtablesize; idx++)
|
||||||
if (fdtable[idx].fd != -1 && (!owner || fdtable[idx].owner == owner))
|
if (fdtable[idx].fd != -1 && (!owner || fdtable[idx].owner == owner))
|
||||||
count++;
|
{
|
||||||
|
if (fdtable[idx].closing)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((flags & FDTABLE_FLAG_DONE) && fdtable[idx].done)
|
||||||
|
count++;
|
||||||
|
else if ((flags & FDTABLE_FLAG_NOT_DONE) && !fdtable[idx].done)
|
||||||
|
count++;
|
||||||
|
else if ((flags & FDTABLE_FLAG_ACTIVE) && fdtable[idx].active)
|
||||||
|
count++;
|
||||||
|
else if (!flags && fdtable[idx].io_cb.cb)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
UNLOCK (fdtable_lock);
|
UNLOCK (fdtable_lock);
|
||||||
|
|
||||||
TRACE (DEBUG_SYSIO, __func__, NULL, "ctx=%lu count=%u",
|
TRACE (DEBUG_SYSIO, __func__, NULL, "ctx=%lu flags=0x%u -> count=%u",
|
||||||
(unsigned long)owner, count);
|
(unsigned long)owner, flags, count);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,9 +485,10 @@ _gpgme_fdtable_io_cb_count (uint64_t owner)
|
|||||||
/* Run all signaled IO callbacks of OWNER or all signaled callbacks if
|
/* Run all signaled IO callbacks of OWNER or all signaled callbacks if
|
||||||
* OWNER is 0. Returns an error code on the first real error
|
* OWNER is 0. Returns an error code on the first real error
|
||||||
* encountered. If R_OP_ERR is not NULL an optional operational error
|
* encountered. If R_OP_ERR is not NULL an optional operational error
|
||||||
* can be stored tehre. For EOF the respective flags are set. */
|
* can be stored there. For EOF the respective flags are set. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
_gpgme_fdtable_run_io_cbs (uint64_t owner, gpg_error_t *r_op_err)
|
_gpgme_fdtable_run_io_cbs (uint64_t owner, gpg_error_t *r_op_err,
|
||||||
|
uint64_t *r_owner)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
int idx;
|
int idx;
|
||||||
@ -485,6 +503,8 @@ _gpgme_fdtable_run_io_cbs (uint64_t owner, gpg_error_t *r_op_err)
|
|||||||
|
|
||||||
if (r_op_err)
|
if (r_op_err)
|
||||||
*r_op_err = 0;
|
*r_op_err = 0;
|
||||||
|
if (r_owner)
|
||||||
|
*r_owner = 0;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@ -543,6 +563,8 @@ _gpgme_fdtable_run_io_cbs (uint64_t owner, gpg_error_t *r_op_err)
|
|||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
_gpgme_cancel_with_err (serial, err, 0);
|
_gpgme_cancel_with_err (serial, err, 0);
|
||||||
|
if (r_owner)
|
||||||
|
*r_owner = serial;
|
||||||
return TRACE_ERR (err);
|
return TRACE_ERR (err);
|
||||||
}
|
}
|
||||||
else if (iocb_data.op_err)
|
else if (iocb_data.op_err)
|
||||||
@ -558,6 +580,8 @@ _gpgme_fdtable_run_io_cbs (uint64_t owner, gpg_error_t *r_op_err)
|
|||||||
* operation. */
|
* operation. */
|
||||||
if (r_op_err)
|
if (r_op_err)
|
||||||
*r_op_err = iocb_data.op_err;
|
*r_op_err = iocb_data.op_err;
|
||||||
|
if (r_owner)
|
||||||
|
*r_owner = serial;
|
||||||
return TRACE_ERR (0);
|
return TRACE_ERR (0);
|
||||||
}
|
}
|
||||||
else if (!cb_count && actx)
|
else if (!cb_count && actx)
|
||||||
@ -606,6 +630,8 @@ _gpgme_fdtable_get_fds (io_select_t *r_fds, uint64_t owner, unsigned int flags)
|
|||||||
continue;
|
continue;
|
||||||
if ((flags & FDTABLE_FLAG_DONE) && !fdtable[idx].done)
|
if ((flags & FDTABLE_FLAG_DONE) && !fdtable[idx].done)
|
||||||
continue;
|
continue;
|
||||||
|
if ((flags & FDTABLE_FLAG_NOT_DONE) && fdtable[idx].done)
|
||||||
|
continue;
|
||||||
if ((flags & FDTABLE_FLAG_FOR_READ) && !fdtable[idx].for_read)
|
if ((flags & FDTABLE_FLAG_FOR_READ) && !fdtable[idx].for_read)
|
||||||
continue;
|
continue;
|
||||||
if ((flags & FDTABLE_FLAG_FOR_WRITE) && !fdtable[idx].for_write)
|
if ((flags & FDTABLE_FLAG_FOR_WRITE) && !fdtable[idx].for_write)
|
||||||
@ -651,6 +677,11 @@ _gpgme_fdtable_get_done (uint64_t owner,
|
|||||||
|
|
||||||
TRACE_BEG (DEBUG_SYSIO, __func__, NULL, "ctx=%lu", (unsigned long)owner);
|
TRACE_BEG (DEBUG_SYSIO, __func__, NULL, "ctx=%lu", (unsigned long)owner);
|
||||||
|
|
||||||
|
if (r_status)
|
||||||
|
*r_status = 0;
|
||||||
|
if (r_op_err)
|
||||||
|
*r_op_err = 0;
|
||||||
|
|
||||||
LOCK (fdtable_lock);
|
LOCK (fdtable_lock);
|
||||||
|
|
||||||
for (idx=0; idx < fdtablesize; idx++)
|
for (idx=0; idx < fdtablesize; idx++)
|
||||||
@ -660,8 +691,11 @@ _gpgme_fdtable_get_done (uint64_t owner,
|
|||||||
/* Found. If an owner has been given also clear the done
|
/* Found. If an owner has been given also clear the done
|
||||||
* flags from all other fds of this owner. Note that they
|
* flags from all other fds of this owner. Note that they
|
||||||
* have the same status info anyway. */
|
* have the same status info anyway. */
|
||||||
*r_status = fdtable[idx].done_status;
|
TRACE_LOG ("found fd=%d", fdtable[idx].fd);
|
||||||
*r_op_err = fdtable[idx].done_op_err;
|
if (r_status)
|
||||||
|
*r_status = fdtable[idx].done_status;
|
||||||
|
if (r_op_err)
|
||||||
|
*r_op_err = fdtable[idx].done_op_err;
|
||||||
fdtable[idx].done = 0;
|
fdtable[idx].done = 0;
|
||||||
serial = fdtable[idx].owner;
|
serial = fdtable[idx].owner;
|
||||||
if (owner)
|
if (owner)
|
||||||
|
@ -26,11 +26,12 @@
|
|||||||
/* Flags used by _gpgme_fdtable_get_fds. */
|
/* Flags used by _gpgme_fdtable_get_fds. */
|
||||||
#define FDTABLE_FLAG_ACTIVE 1 /* Only those with the active flag set. */
|
#define FDTABLE_FLAG_ACTIVE 1 /* Only those with the active flag set. */
|
||||||
#define FDTABLE_FLAG_DONE 2 /* Only those with the done flag set */
|
#define FDTABLE_FLAG_DONE 2 /* Only those with the done flag set */
|
||||||
#define FDTABLE_FLAG_FOR_READ 4 /* Only those with the signaled flag set. */
|
#define FDTABLE_FLAG_NOT_DONE 4 /* Only those with the done flag cleared. */
|
||||||
#define FDTABLE_FLAG_FOR_WRITE 8 /* Only those with the for_read flag set. */
|
#define FDTABLE_FLAG_FOR_READ 16 /* Only those with the signaled flag set. */
|
||||||
#define FDTABLE_FLAG_SIGNALED 16 /* Only those with the signaled flag set. */
|
#define FDTABLE_FLAG_FOR_WRITE 32 /* Only those with the for_read flag set. */
|
||||||
#define FDTABLE_FLAG_NOT_SIGNALED 32 /* Ditto reversed. */
|
#define FDTABLE_FLAG_SIGNALED 64 /* Only those with the signaled flag set. */
|
||||||
#define FDTABLE_FLAG_CLEAR 128 /* Clear the signaled flag. */
|
#define FDTABLE_FLAG_NOT_SIGNALED 128 /* Ditto reversed. */
|
||||||
|
#define FDTABLE_FLAG_CLEAR 256 /* Clear the signaled flag. */
|
||||||
|
|
||||||
|
|
||||||
/* The handler type associated with an FD. It is called with the FD
|
/* The handler type associated with an FD. It is called with the FD
|
||||||
@ -65,10 +66,11 @@ void _gpgme_fdtable_set_signaled (io_select_t fds, unsigned int nfds);
|
|||||||
gpg_error_t _gpgme_fdtable_remove (int fd);
|
gpg_error_t _gpgme_fdtable_remove (int fd);
|
||||||
|
|
||||||
/* Return the number of active I/O callbacks for OWNER. */
|
/* Return the number of active I/O callbacks for OWNER. */
|
||||||
unsigned int _gpgme_fdtable_io_cb_count (uint64_t owner);
|
unsigned int _gpgme_fdtable_get_count (uint64_t owner, unsigned int flags);
|
||||||
|
|
||||||
/* Run all the signaled IO callbacks of OWNER. */
|
/* Run all the signaled IO callbacks of OWNER. */
|
||||||
gpg_error_t _gpgme_fdtable_run_io_cbs (uint64_t owner, gpg_error_t *r_op_err);
|
gpg_error_t _gpgme_fdtable_run_io_cbs (uint64_t owner, gpg_error_t *r_op_err,
|
||||||
|
uint64_t *r_owner);
|
||||||
|
|
||||||
/* Return a list of FDs matching the OWNER and FLAGS. */
|
/* Return a list of FDs matching the OWNER and FLAGS. */
|
||||||
unsigned int _gpgme_fdtable_get_fds (io_select_t *r_fds,
|
unsigned int _gpgme_fdtable_get_fds (io_select_t *r_fds,
|
||||||
|
79
src/wait.c
79
src/wait.c
@ -58,10 +58,10 @@ user_io_cb_handler (void *data, int fd)
|
|||||||
serial = tag->serial;
|
serial = tag->serial;
|
||||||
assert (serial);
|
assert (serial);
|
||||||
|
|
||||||
err = _gpgme_fdtable_run_io_cbs (serial, &op_err);
|
err = _gpgme_fdtable_run_io_cbs (serial, &op_err, NULL);
|
||||||
if (err || op_err)
|
if (err || op_err)
|
||||||
;
|
;
|
||||||
else if (!_gpgme_fdtable_io_cb_count (serial))
|
else if (!_gpgme_fdtable_get_count (serial, 0))
|
||||||
{
|
{
|
||||||
/* No more active callbacks - emit a DONE. */
|
/* No more active callbacks - emit a DONE. */
|
||||||
struct gpgme_io_event_done_data done_data = { 0, 0 };
|
struct gpgme_io_event_done_data done_data = { 0, 0 };
|
||||||
@ -318,10 +318,20 @@ gpgme_wait_ext (gpgme_ctx_t ctx, gpgme_error_t *status,
|
|||||||
int nr;
|
int nr;
|
||||||
uint64_t serial;
|
uint64_t serial;
|
||||||
|
|
||||||
|
TRACE_BEG (DEBUG_SYSIO, __func__, NULL, "ctx=%lu hang=%d",
|
||||||
|
CTXSERIAL (ctx), hang);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* Get all fds of CTX (or all if CTX is NULL) we want to wait
|
/* Get all fds of CTX (or all if CTX is NULL) we want to wait
|
||||||
* for and which are in the active state. */
|
* for and which are in the active state. */
|
||||||
|
TRACE_LOG
|
||||||
|
("active=%u done=%u !done=%d cbs=%u",
|
||||||
|
_gpgme_fdtable_get_count (ctx?ctx->serial:0,FDTABLE_FLAG_ACTIVE),
|
||||||
|
_gpgme_fdtable_get_count (ctx?ctx->serial:0,FDTABLE_FLAG_DONE),
|
||||||
|
_gpgme_fdtable_get_count (ctx?ctx->serial:0,FDTABLE_FLAG_NOT_DONE),
|
||||||
|
_gpgme_fdtable_get_count (ctx?ctx->serial:0,0));
|
||||||
|
|
||||||
free (fds);
|
free (fds);
|
||||||
nfds = _gpgme_fdtable_get_fds (&fds, ctx? ctx->serial : 0,
|
nfds = _gpgme_fdtable_get_fds (&fds, ctx? ctx->serial : 0,
|
||||||
( FDTABLE_FLAG_ACTIVE
|
( FDTABLE_FLAG_ACTIVE
|
||||||
@ -335,11 +345,22 @@ gpgme_wait_ext (gpgme_ctx_t ctx, gpgme_error_t *status,
|
|||||||
*status = err;
|
*status = err;
|
||||||
if (op_err)
|
if (op_err)
|
||||||
*op_err = 0;
|
*op_err = 0;
|
||||||
free (fds);
|
ctx = NULL;
|
||||||
return NULL;
|
goto leave;
|
||||||
}
|
}
|
||||||
/* Nothing to select. Run the select anyway, so that we use
|
/* Nothing to select. */
|
||||||
* its timeout. */
|
|
||||||
|
if (!_gpgme_fdtable_get_count (ctx? ctx->serial : 0,
|
||||||
|
FDTABLE_FLAG_NOT_DONE))
|
||||||
|
{
|
||||||
|
if (status)
|
||||||
|
*status = 0;
|
||||||
|
if (op_err)
|
||||||
|
*op_err = 0;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
/* There are not yet active FDS. Use the select's standard
|
||||||
|
* timeout and then try again. */
|
||||||
}
|
}
|
||||||
|
|
||||||
nr = _gpgme_io_select (fds, nfds, 0);
|
nr = _gpgme_io_select (fds, nfds, 0);
|
||||||
@ -349,30 +370,48 @@ gpgme_wait_ext (gpgme_ctx_t ctx, gpgme_error_t *status,
|
|||||||
*status = gpg_error_from_syserror ();
|
*status = gpg_error_from_syserror ();
|
||||||
if (op_err)
|
if (op_err)
|
||||||
*op_err = 0;
|
*op_err = 0;
|
||||||
free (fds);
|
ctx = NULL;
|
||||||
return NULL;
|
goto leave;
|
||||||
}
|
}
|
||||||
_gpgme_fdtable_set_signaled (fds, nfds);
|
_gpgme_fdtable_set_signaled (fds, nfds);
|
||||||
|
|
||||||
_gpgme_fdtable_run_io_cbs (ctx? ctx->serial : 0, NULL);
|
err = _gpgme_fdtable_run_io_cbs (ctx? ctx->serial : 0, op_err, &serial);
|
||||||
serial = _gpgme_fdtable_get_done (ctx? ctx->serial : 0, status, op_err);
|
if (err || (op_err && *op_err))
|
||||||
if (serial)
|
|
||||||
{
|
{
|
||||||
_gpgme_get_ctx (serial, &ctx);
|
if (status)
|
||||||
|
*status = err;
|
||||||
|
if (serial)
|
||||||
|
_gpgme_get_ctx (serial, &ctx);
|
||||||
hang = 0;
|
hang = 0;
|
||||||
}
|
}
|
||||||
else if (!hang)
|
else
|
||||||
{
|
{
|
||||||
ctx = NULL;
|
serial = _gpgme_fdtable_get_done (ctx? ctx->serial : 0, status,
|
||||||
if (status)
|
op_err);
|
||||||
*status = 0;
|
if (serial)
|
||||||
if (op_err)
|
{
|
||||||
*op_err = 0;
|
_gpgme_get_ctx (serial, &ctx);
|
||||||
|
hang = 0;
|
||||||
|
}
|
||||||
|
else if (!hang)
|
||||||
|
{
|
||||||
|
ctx = NULL;
|
||||||
|
if (status)
|
||||||
|
*status = 0;
|
||||||
|
if (op_err)
|
||||||
|
*op_err = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (hang);
|
while (hang);
|
||||||
|
|
||||||
|
leave:
|
||||||
free (fds);
|
free (fds);
|
||||||
|
if (status)
|
||||||
|
TRACE_LOG ("status=%d", *status);
|
||||||
|
if (op_err)
|
||||||
|
TRACE_LOG ("op_err=%d", *op_err);
|
||||||
|
TRACE_SUC ("result=%lu", ctx? ctx->serial : 0);
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -434,12 +473,12 @@ _gpgme_sync_wait (gpgme_ctx_t ctx, volatile int *cond, gpg_error_t *r_op_err)
|
|||||||
}
|
}
|
||||||
_gpgme_fdtable_set_signaled (fds, nfds);
|
_gpgme_fdtable_set_signaled (fds, nfds);
|
||||||
|
|
||||||
err = _gpgme_fdtable_run_io_cbs (ctx->serial, r_op_err);
|
err = _gpgme_fdtable_run_io_cbs (ctx->serial, r_op_err, NULL);
|
||||||
if (err || (r_op_err && *r_op_err))
|
if (err || (r_op_err && *r_op_err))
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_gpgme_fdtable_io_cb_count (ctx->serial))
|
if (!_gpgme_fdtable_get_count (ctx->serial, 0))
|
||||||
{
|
{
|
||||||
/* No more matching fds with IO callbacks. */
|
/* No more matching fds with IO callbacks. */
|
||||||
struct gpgme_io_event_done_data data = {0, 0};
|
struct gpgme_io_event_done_data data = {0, 0};
|
||||||
|
@ -59,7 +59,7 @@ main (void)
|
|||||||
fail_if_err (err);
|
fail_if_err (err);
|
||||||
|
|
||||||
while (gpgme_wait (ctx, &err, 0) == NULL && err == 0)
|
while (gpgme_wait (ctx, &err, 0) == NULL && err == 0)
|
||||||
sleep(1);
|
;
|
||||||
|
|
||||||
if (gpgme_err_code (err) != GPG_ERR_NO_DATA)
|
if (gpgme_err_code (err) != GPG_ERR_NO_DATA)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user