From 7bd07d62f3d89c037f255478327a577a737f01b5 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 19 Feb 2001 17:22:38 +0000 Subject: [PATCH] FD are now released and a major bug has been fixed. The W32 version does not compile at the meoment. --- TODO | 3 --- gpgme/ChangeLog | 19 +++++++++++++++ gpgme/io.h | 2 ++ gpgme/posix-io.c | 32 ++++++++++++++++++++++++- gpgme/rungpg.c | 61 +++++++++++++++++++++++++++++++++++++++++------- gpgme/verify.c | 2 +- gpgme/wait.c | 21 +++++++---------- tests/t-verify.c | 3 +++ 8 files changed, 118 insertions(+), 25 deletions(-) diff --git a/TODO b/TODO index 1ef478da..c6f65057 100644 --- a/TODO +++ b/TODO @@ -5,7 +5,4 @@ * Allow to use GTK's main loop instead of the select stuff in wait.c -* a op_keylist_start should cancel a pending keylisy operation on the - same context - * need to close a lot of handles in w32-io.c diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index bcb71352..0c8722e8 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,22 @@ +2001-02-19 Werner Koch + + * posix-io.c (_gpgme_io_select): Use a 1 sec timeout and not 200 + microseconds. + + * wait.c (remove_process): Don't close the fd here. + (do_select): Set the fd to -1 and remove the is_closed flag everywhere. + (_gpgme_wait_on_condition): Remove the assert on the queue and + break out if we could not find the queue. The whole thing should + be reworked. + + * posix-io.c (_gpgme_io_set_close_notify): New. + (_gpgme_io_close): Do the notification. + + * rungpg.c (close_notify_handler): New. + (_gpgme_gpg_new): Register a callback for the fd. + (_gpgme_gpg_set_colon_line_handler): Ditto. + (build_argv): Ditto + 2001-02-13 Werner Koch * rungpg.c (struct reap_s): Replaced pid_t by int. diff --git a/gpgme/io.h b/gpgme/io.h index efe2c785..2f9f1b7f 100644 --- a/gpgme/io.h +++ b/gpgme/io.h @@ -46,6 +46,8 @@ int _gpgme_io_read ( int fd, void *buffer, size_t count ); int _gpgme_io_write ( int fd, const void *buffer, size_t count ); int _gpgme_io_pipe ( int filedes[2], int inherit_idx ); int _gpgme_io_close ( int fd ); +int _gpgme_io_set_close_notify (int fd, + void (*handler)(int, void*), void *value); int _gpgme_io_set_nonblocking ( int fd ); int _gpgme_io_spawn ( const char *path, char **argv, struct spawn_fd_item_s *fd_child_list, diff --git a/gpgme/posix-io.c b/gpgme/posix-io.c index 2e7e2c96..3cd2bd5a 100644 --- a/gpgme/posix-io.c +++ b/gpgme/posix-io.c @@ -36,6 +36,12 @@ #include "util.h" #include "io.h" +static struct { + void (*handler)(int,void*); + void *value; +} notify_table[256]; + + int _gpgme_io_read ( int fd, void *buffer, size_t count ) { @@ -75,9 +81,33 @@ _gpgme_io_close ( int fd ) { if ( fd == -1 ) return -1; + /* first call the notify handler */ + DEBUG1 ("closing fd %d", fd ); + if ( fd >= 0 && fd < DIM (notify_table) ) { + if (notify_table[fd].handler) { + notify_table[fd].handler (fd, notify_table[fd].value); + notify_table[fd].handler = NULL; + notify_table[fd].value = NULL; + } + } + /* then do the close */ return close (fd); } +int +_gpgme_io_set_close_notify (int fd, void (*handler)(int, void*), void *value) +{ + assert (fd != -1); + + if ( fd < 0 || fd >= DIM (notify_table) ) + return -1; + DEBUG1 ("set notification for fd %d", fd ); + notify_table[fd].handler = handler; + notify_table[fd].value = value; + return 0; +} + + int _gpgme_io_set_nonblocking ( int fd ) { @@ -225,7 +255,7 @@ _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds ) static fd_set readfds; static fd_set writefds; int any, i, max_fd, n, count; - struct timeval timeout = { 0, 200 }; /* Use a 200ms timeout */ + struct timeval timeout = { 1, 0 }; /* Use a 1s timeout */ void *dbg_help; FD_ZERO ( &readfds ); diff --git a/gpgme/rungpg.c b/gpgme/rungpg.c index 261c71f7..b042d7b7 100644 --- a/gpgme/rungpg.c +++ b/gpgme/rungpg.c @@ -145,6 +145,38 @@ static int command_cb ( void *opaque, char *buffer, size_t length, size_t *nread ); +static void +close_notify_handler ( int fd, void *opaque ) +{ + GpgObject gpg = opaque; + + assert (fd != -1); + if (gpg->status.fd[0] == fd ) + gpg->status.fd[0] = -1; + else if (gpg->status.fd[1] == fd ) + gpg->status.fd[1] = -1; + else if (gpg->colon.fd[0] == fd ) + gpg->colon.fd[0] = -1; + else if (gpg->colon.fd[1] == fd ) + gpg->colon.fd[1] = -1; + else if (gpg->fd_data_map) { + int i; + + for (i=0; gpg->fd_data_map[i].data; i++ ) { + if ( gpg->fd_data_map[i].fd == fd ) { + gpg->fd_data_map[i].fd = -1; + break; + } + if ( gpg->fd_data_map[i].peer_fd == fd ) { + gpg->fd_data_map[i].peer_fd = -1; + break; + } + } + } +} + + + GpgmeError _gpgme_gpg_new ( GpgObject *r_gpg ) @@ -179,6 +211,13 @@ _gpgme_gpg_new ( GpgObject *r_gpg ) rc = mk_error (Pipe_Error); goto leave; } + if ( _gpgme_io_set_close_notify (gpg->status.fd[0], + close_notify_handler, gpg) + || _gpgme_io_set_close_notify (gpg->status.fd[1], + close_notify_handler, gpg) ) { + rc = mk_error (General_Error); + goto leave; + } gpg->status.eof = 0; _gpgme_gpg_add_arg ( gpg, "--status-fd" ); { @@ -211,11 +250,6 @@ _gpgme_gpg_release ( GpgObject gpg ) free_argv (gpg->argv); xfree (gpg->cmd.keyword); - #if 0 - /* fixme: We need a way to communicate back closed fds, so that we - * don't do it a second time. One way to do it is by using a global - * table of open fds associated with gpg objects - but this requires - * additional locking. */ if (gpg->status.fd[0] != -1 ) _gpgme_io_close (gpg->status.fd[0]); if (gpg->status.fd[1] != -1 ) @@ -224,7 +258,6 @@ _gpgme_gpg_release ( GpgObject gpg ) _gpgme_io_close (gpg->colon.fd[0]); if (gpg->colon.fd[1] != -1 ) _gpgme_io_close (gpg->colon.fd[1]); - #endif free_fd_data_map (gpg->fd_data_map); if (gpg->running) { int pid = gpg->pid; @@ -246,6 +279,7 @@ _gpgme_gpg_release ( GpgObject gpg ) xfree (gpg); } + static void do_reaping (void) { @@ -438,6 +472,12 @@ _gpgme_gpg_set_colon_line_handler ( GpgObject gpg, xfree (gpg->colon.buffer); gpg->colon.buffer = NULL; return mk_error (Pipe_Error); } + if ( _gpgme_io_set_close_notify (gpg->colon.fd[0], + close_notify_handler, gpg) + || _gpgme_io_set_close_notify (gpg->colon.fd[1], + close_notify_handler, gpg) ) { + return mk_error (General_Error); + } gpg->colon.eof = 0; gpg->colon.fnc = fnc; gpg->colon.fnc_value = fnc_value; @@ -512,12 +552,10 @@ free_fd_data_map ( struct fd_data_map_s *fd_data_map ) return; for (i=0; fd_data_map[i].data; i++ ) { -#if 0 /* fixme -> see gpg_release */ if ( fd_data_map[i].fd != -1 ) _gpgme_io_close (fd_data_map[i].fd); if ( fd_data_map[i].peer_fd != -1 ) _gpgme_io_close (fd_data_map[i].peer_fd); -#endif /* don't release data because this is only a reference */ } xfree (fd_data_map); @@ -652,6 +690,13 @@ build_argv ( GpgObject gpg ) free_argv (argv); return mk_error (Pipe_Error); } + if ( _gpgme_io_set_close_notify (fds[0], + close_notify_handler, gpg) + || _gpgme_io_set_close_notify (fds[1], + close_notify_handler, + gpg)) { + return mk_error (General_Error); + } /* if the data_type is FD, we have to do a dup2 here */ if (fd_data_map[datac].inbound) { fd_data_map[datac].fd = fds[0]; diff --git a/gpgme/verify.c b/gpgme/verify.c index 7a1af985..ce6a2bac 100644 --- a/gpgme/verify.c +++ b/gpgme/verify.c @@ -406,7 +406,7 @@ gpgme_get_sig_status (GpgmeCtx c, int idx, * * Return a key object which was used to check the signature. * - * Return value: An Errorcode or 0 for success. GPGpid == pid ) { xfree (q); fd_table[i].opaque = NULL; - - if ( !fd_table[i].is_closed ) { - _gpgme_io_close (fd_table[i].fd); - fd_table[i].is_closed = 1; - } fd_table[i].fd = -1; } } @@ -151,12 +147,14 @@ _gpgme_wait_on_condition ( GpgmeCtx c, int hang, volatile int *cond ) * alive */ assert (c); /* !c is not yet implemented */ q = queue_item_from_context ( c ); - assert (q); - - if ( !count_active_and_thawed_fds (q->pid) ) { - remove_process (q->pid); - hang = 0; + if (q) { + if ( !count_active_and_thawed_fds (q->pid) ) { + remove_process (q->pid); + hang = 0; + } } + else + hang = 0; } if (hang) run_idle (); @@ -201,7 +199,7 @@ do_select ( void ) q->active = 0; fd_table[i].for_read = 0; fd_table[i].for_write = 0; - fd_table[i].is_closed = 1; + fd_table[i].fd = -1; } } } @@ -242,7 +240,6 @@ _gpgme_register_pipe_handler ( void *opaque, for (i=0; i < fd_table_size; i++ ) { if ( fd_table[i].fd == -1 ) { fd_table[i].fd = fd; - fd_table[i].is_closed = 0; fd_table[i].for_read = inbound; fd_table[i].for_write = !inbound; fd_table[i].signaled = 0; diff --git a/tests/t-verify.c b/tests/t-verify.c index 9372a7c6..e0fbbe34 100644 --- a/tests/t-verify.c +++ b/tests/t-verify.c @@ -150,6 +150,9 @@ main (int argc, char **argv ) puts ("checking a valid message:\n"); err = gpgme_op_verify (ctx, sig, text, &status ); print_sig_stat ( ctx, status ); + print_sig_stat ( ctx, status ); + print_sig_stat ( ctx, status ); + print_sig_stat ( ctx, status ); fail_if_err (err); if ( (nota=gpgme_get_notation (ctx)) )