Fixed W32 bugs and one major bug which swallowed up some output.

This commit is contained in:
Werner Koch 2001-01-31 12:39:53 +00:00
parent 1316aed172
commit 1648829c39
7 changed files with 103 additions and 108 deletions

4
TODO
View File

@ -5,6 +5,4 @@
* Allow to use GTK's main loop instead of the select stuff in * Allow to use GTK's main loop instead of the select stuff in
wait.c wait.c
* Remove all that funny exit code handling - we don't need it. * need to close a lot of handles in w32-io.c

View File

@ -1,3 +1,13 @@
2001-01-31 Werner Koch <wk@gnupg.org>
* wait.c (_gpgme_wait_on_condition): Remove all exit code processing.
(propagate_term_results,clear_active_fds): Removed.
(count_active_fds): Renamed to ..
(count_active_and_thawed_fds): .. this and count only thawed fds.
* rungpg.c (gpg_colon_line_handler): Return colon.eof and not
status.eof ;-)
2001-01-30 Werner Koch <wk@gnupg.org> 2001-01-30 Werner Koch <wk@gnupg.org>
* w32-io.c (_gpgme_io_spawn): Use the supplied path arg. * w32-io.c (_gpgme_io_spawn): Use the supplied path arg.

View File

@ -139,6 +139,7 @@ _gpgme_debug_end (void **helper, const char *text)
return; return;
_gpgme_debug_add (helper, "%s", text ); _gpgme_debug_add (helper, "%s", text );
fflush (ctl->fp); /* we need this for the buggy Windoze libc */
rewind (ctl->fp); rewind (ctl->fp);
LOCK (debug_lock); LOCK (debug_lock);
while ( (c=getc (ctl->fp)) != EOF ) { while ( (c=getc (ctl->fp)) != EOF ) {
@ -149,6 +150,7 @@ _gpgme_debug_end (void **helper, const char *text)
putc ('\n', stderr); putc ('\n', stderr);
UNLOCK (debug_lock); UNLOCK (debug_lock);
fclose (ctl->fp);
remove (ctl->fname); remove (ctl->fname);
xfree (ctl); xfree (ctl);
*helper = NULL; *helper = NULL;

View File

@ -1018,7 +1018,8 @@ read_status ( GpgObject gpg )
} }
} }
if ( r->code == STATUS_END_STREAM ) { if ( r->code == STATUS_END_STREAM ) {
/* _gpgme_freeze_fd ( ? );*/ if ( gpg->cmd.used )
_gpgme_freeze_fd ( gpg->cmd.fd );
} }
} }
/* To reuse the buffer for the next line we have to /* To reuse the buffer for the next line we have to
@ -1066,7 +1067,7 @@ gpg_colon_line_handler ( void *opaque, int pid, int fd )
return 1; return 1;
} }
return gpg->status.eof; return gpg->colon.eof;
} }
static GpgmeError static GpgmeError

View File

@ -216,14 +216,14 @@ version_line_handler ( GpgmeCtx c, char *line )
static const char * static const char *
get_engine_info (void) get_engine_info (void)
{ {
const char *engine_info =NULL; static const char *engine_info =NULL;
GpgmeCtx c = NULL; GpgmeCtx c = NULL;
GpgmeError err = 0; GpgmeError err = 0;
const char *path = NULL; const char *path = NULL;
/* FIXME: make sure that only one instance does run */ /* FIXME: make sure that only one instance does run */
if (engine_info) if (engine_info)
goto leave; return engine_info;
path = _gpgme_get_gpg_path (); path = _gpgme_get_gpg_path ();
err = gpgme_new (&c); err = gpgme_new (&c);
@ -299,3 +299,7 @@ get_engine_info (void)
} }

View File

@ -58,12 +58,11 @@ struct reader_context_s {
DECLARE_LOCK (mutex); DECLARE_LOCK (mutex);
int eof; int eof;
int eof_shortcut;
int error; int error;
int error_code; int error_code;
HANDLE have_data_ev; /* manually reset */ HANDLE have_data_ev; /* manually reset */
int have_data_flag; /* FIXME: is there another way to check whether
it has been signaled? */
HANDLE have_space_ev; /* auto reset */ HANDLE have_space_ev; /* auto reset */
size_t readpos, writepos; size_t readpos, writepos;
char buffer[READBUF_SIZE]; char buffer[READBUF_SIZE];
@ -128,10 +127,17 @@ reader (void *arg)
DEBUG2 ("reader thread %p: reading %d bytes", c->thread_hd, nbytes ); DEBUG2 ("reader thread %p: reading %d bytes", c->thread_hd, nbytes );
if ( !ReadFile ( c->file_hd, if ( !ReadFile ( c->file_hd,
c->buffer+c->writepos, nbytes, &nread, NULL) ) { c->buffer+c->writepos, nbytes, &nread, NULL) ) {
c->error = 1;
c->error_code = (int)GetLastError (); c->error_code = (int)GetLastError ();
if (c->error_code == ERROR_BROKEN_PIPE ) {
c->eof=1;
DEBUG1 ("reader thread %p: got eof (broken pipe)",
c->thread_hd );
}
else {
c->error = 1;
DEBUG2 ("reader thread %p: read error: ec=%d", DEBUG2 ("reader thread %p: read error: ec=%d",
c->thread_hd, c->error_code ); c->thread_hd, c->error_code );
}
break; break;
} }
if ( !nread ) { if ( !nread ) {
@ -143,10 +149,11 @@ reader (void *arg)
LOCK (c->mutex); LOCK (c->mutex);
c->writepos = (c->writepos + nread) % READBUF_SIZE; c->writepos = (c->writepos + nread) % READBUF_SIZE;
c->have_data_flag = 1;
SetEvent (c->have_data_ev); SetEvent (c->have_data_ev);
UNLOCK (c->mutex); UNLOCK (c->mutex);
} }
/* indicate that we have an error or eof */
SetEvent (c->have_data_ev);
DEBUG1 ("reader thread %p ended", c->thread_hd ); DEBUG1 ("reader thread %p ended", c->thread_hd );
return 0; return 0;
@ -245,20 +252,33 @@ _gpgme_io_read ( int fd, void *buffer, size_t count )
DEBUG0 ( "no reader thread\n"); DEBUG0 ( "no reader thread\n");
return -1; return -1;
} }
if (c->eof_shortcut) {
DEBUG1 ("fd %d: EOF (again)", fd );
return 0;
}
LOCK (c->mutex); LOCK (c->mutex);
if (c->readpos == c->writepos) { /* no data avail */ if (c->readpos == c->writepos && !c->error) { /*no data avail*/
UNLOCK (c->mutex); UNLOCK (c->mutex);
DEBUG2 ("fd %d: waiting for data from thread %p", fd, c->thread_hd); DEBUG2 ("fd %d: waiting for data from thread %p", fd, c->thread_hd);
WaitForSingleObject (c->have_data_ev, INFINITE); WaitForSingleObject (c->have_data_ev, INFINITE);
DEBUG2 ("fd %d: data from thread %p available", fd, c->thread_hd); DEBUG2 ("fd %d: data from thread %p available", fd, c->thread_hd);
LOCK (c->mutex); LOCK (c->mutex);
if (c->readpos == c->writepos && !c->eof && !c->error) {
UNLOCK (c->mutex);
if (c->eof)
return 0;
return -1;
} }
if (c->readpos == c->writepos || c->error) {
UNLOCK (c->mutex);
c->eof_shortcut = 1;
if (c->eof) {
DEBUG1 ("fd %d: EOF", fd );
return 0;
}
if (!c->error) {
DEBUG1 ("fd %d: EOF but eof flag not set", fd );
return 0;
}
DEBUG1 ("fd %d: read error", fd );
return -1;
} }
nread = c->readpos < c->writepos? c->writepos - c->readpos nread = c->readpos < c->writepos? c->writepos - c->readpos
@ -267,11 +287,9 @@ _gpgme_io_read ( int fd, void *buffer, size_t count )
nread = count; nread = count;
memcpy (buffer, c->buffer+c->readpos, nread); memcpy (buffer, c->buffer+c->readpos, nread);
c->readpos = (c->readpos + nread) % READBUF_SIZE; c->readpos = (c->readpos + nread) % READBUF_SIZE;
if (c->readpos == c->writepos) { if (c->readpos == c->writepos && !c->eof) {
c->have_data_flag = 0;
ResetEvent (c->have_data_ev); ResetEvent (c->have_data_ev);
} }
if (nread)
SetEvent (c->have_space_ev); SetEvent (c->have_space_ev);
UNLOCK (c->mutex); UNLOCK (c->mutex);
@ -287,9 +305,9 @@ _gpgme_io_write ( int fd, const void *buffer, size_t count )
DWORD nwritten; DWORD nwritten;
HANDLE h = fd_to_handle (fd); HANDLE h = fd_to_handle (fd);
#warning writing blocks for large counts, so we limit it here. /* writing blocks for large counts, so we limit it here. */
if (count > 500) if (count > 1024)
count = 500; count = 1024;
DEBUG2 ("fd %d: about to write %d bytes\n", fd, (int)count ); DEBUG2 ("fd %d: about to write %d bytes\n", fd, (int)count );
if ( !WriteFile ( h, buffer, count, &nwritten, NULL) ) { if ( !WriteFile ( h, buffer, count, &nwritten, NULL) ) {
@ -587,6 +605,7 @@ _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
{ {
#if 1 #if 1
HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS]; HANDLE waitbuf[MAXIMUM_WAIT_OBJECTS];
int waitidx[MAXIMUM_WAIT_OBJECTS];
int code, nwait; int code, nwait;
int i, any, any_write; int i, any, any_write;
int count; int count;
@ -599,20 +618,20 @@ _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
for ( i=0; i < nfds; i++ ) { for ( i=0; i < nfds; i++ ) {
if ( fds[i].fd == -1 ) if ( fds[i].fd == -1 )
continue; continue;
if ( fds[i].for_read || fds[i].for_write ) {
if ( fds[i].for_read ) { if ( fds[i].for_read ) {
struct reader_context_s *c = find_reader (fds[i].fd,1);
if (!c) {
DEBUG1 ("oops: no reader thread for fd %d", fds[i].fd);
}
else {
if ( nwait >= DIM (waitbuf) ) { if ( nwait >= DIM (waitbuf) ) {
DEBUG_END (dbg_help, "oops ]"); DEBUG_END (dbg_help, "oops ]");
DEBUG0 ("Too many objects for WFMO!" ); DEBUG0 ("Too many objects for WFMO!" );
return -1; return -1;
} }
else { waitidx[nwait] = i;
if ( fds[i].for_read ) {
struct reader_context_s *c = find_reader (fds[i].fd,1);
if (!c) {
DEBUG1 ("no reader thread for fd %d", fds[i].fd);
}
else {
waitbuf[nwait++] = c->have_data_ev; waitbuf[nwait++] = c->have_data_ev;
} }
} }
@ -620,7 +639,6 @@ _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
fds[i].for_read? 'r':'w',fds[i].fd ); fds[i].for_read? 'r':'w',fds[i].fd );
any = 1; any = 1;
} }
}
fds[i].signaled = 0; fds[i].signaled = 0;
} }
DEBUG_END (dbg_help, "]"); DEBUG_END (dbg_help, "]");
@ -651,7 +669,8 @@ _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
any = 0; any = 0;
for (i=code - WAIT_OBJECT_0; i < nwait; i++ ) { for (i=code - WAIT_OBJECT_0; i < nwait; i++ ) {
if (WaitForSingleObject ( waitbuf[i], NULL ) == WAIT_OBJECT_0) { if (WaitForSingleObject ( waitbuf[i], NULL ) == WAIT_OBJECT_0) {
fds[i].signaled = 1; assert (waitidx[i] >=0 && waitidx[i] < nfds);
fds[waitidx[i]].signaled = 1;
any = 1; any = 1;
count++; count++;
} }
@ -686,6 +705,19 @@ _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
count = -1; count = -1;
} }
if ( count ) {
DEBUG_BEGIN (dbg_help, " signaled [ ");
for ( i=0; i < nfds; i++ ) {
if ( fds[i].fd == -1 )
continue;
if ( (fds[i].for_read || fds[i].for_write) && fds[i].signaled ) {
DEBUG_ADD2 (dbg_help, "%c%d ",
fds[i].for_read? 'r':'w',fds[i].fd );
}
}
DEBUG_END (dbg_help, "]");
}
return count; return count;
#else /* This is the code we use */ #else /* This is the code we use */
int i, any, count; int i, any, count;

View File

@ -53,9 +53,6 @@ struct wait_item_s {
void *handler_value; void *handler_value;
int pid; int pid;
int inbound; /* this is an inbound data handler fd */ int inbound; /* this is an inbound data handler fd */
int exited;
int exit_status;
int exit_signal;
GpgmeCtx ctx; GpgmeCtx ctx;
}; };
@ -82,51 +79,20 @@ queue_item_from_context ( GpgmeCtx ctx )
} }
static void
propagate_term_results ( const struct wait_item_s *first_q )
{
struct wait_item_s *q;
int i;
for (i=0; i < fd_table_size; i++ ) {
if ( fd_table[i].fd != -1 && (q=fd_table[i].opaque)
&& q != first_q && !q->exited
&& q->pid == first_q->pid ) {
q->exited = first_q->exited;
q->exit_status = first_q->exit_status;
q->exit_signal = first_q->exit_signal;
}
}
}
static int static int
count_active_fds ( int pid ) count_active_and_thawed_fds ( int pid )
{ {
struct wait_item_s *q; struct wait_item_s *q;
int i, count = 0; int i, count = 0;
for (i=0; i < fd_table_size; i++ ) { for (i=0; i < fd_table_size; i++ ) {
if ( fd_table[i].fd != -1 && (q=fd_table[i].opaque) if ( fd_table[i].fd != -1 && (q=fd_table[i].opaque)
&& q->active && q->pid == pid ) && q->active && !fd_table[i].frozen && q->pid == pid )
count++; count++;
} }
return count; return count;
} }
static void
clear_active_fds ( int pid )
{
struct wait_item_s *q;
int i;
for (i=0; i < fd_table_size; i++ ) {
if ( fd_table[i].fd != -1 && (q=fd_table[i].opaque)
&& q->active && q->pid == pid )
q->active = 0;
}
}
/* remove the given process from the queue */ /* remove the given process from the queue */
static void static void
remove_process ( int pid ) remove_process ( int pid )
@ -187,30 +153,11 @@ _gpgme_wait_on_condition ( GpgmeCtx c, int hang, volatile int *cond )
q = queue_item_from_context ( c ); q = queue_item_from_context ( c );
assert (q); assert (q);
if (q->exited) { if ( !count_active_and_thawed_fds (q->pid) ) {
/* this is the second time we reached this and we got no
* more data from the pipe (which may happen due to buffering).
* Set all FDs inactive.
*/
clear_active_fds (q->pid);
}
else if ( _gpgme_io_waitpid (q->pid, 0,
&q->exit_status, &q->exit_signal)){
q->exited = 1;
propagate_term_results (q);
}
if ( q->exited ) {
if ( !count_active_fds (q->pid) ) {
/* Hmmm, as long as we don't have a callback for
* the exit status, we have no use for these
* values and therefore we can remove this from
* the queue */
remove_process (q->pid); remove_process (q->pid);
hang = 0; hang = 0;
} }
} }
}
if (hang) if (hang)
run_idle (); run_idle ();
} while (hang && !c->cancel ); } while (hang && !c->cancel );
@ -250,6 +197,7 @@ do_select ( void )
any = 1; any = 1;
if ( q->active && q->handler (q->handler_value, if ( q->active && q->handler (q->handler_value,
q->pid, fd_table[i].fd ) ) { q->pid, fd_table[i].fd ) ) {
DEBUG1 ("setting fd %d inactive", fd_table[i].fd );
q->active = 0; q->active = 0;
fd_table[i].for_read = 0; fd_table[i].for_read = 0;
fd_table[i].for_write = 0; fd_table[i].for_write = 0;
@ -334,7 +282,7 @@ _gpgme_freeze_fd ( int fd )
for (i=0; i < fd_table_size; i++ ) { for (i=0; i < fd_table_size; i++ ) {
if ( fd_table[i].fd == fd ) { if ( fd_table[i].fd == fd ) {
fd_table[i].frozen = 1; fd_table[i].frozen = 1;
/*fprintf (stderr, "** FD %d frozen\n", fd );*/ DEBUG1 ("fd %d frozen", fd );
break; break;
} }
} }
@ -350,7 +298,7 @@ _gpgme_thaw_fd ( int fd )
for (i=0; i < fd_table_size; i++ ) { for (i=0; i < fd_table_size; i++ ) {
if ( fd_table[i].fd == fd ) { if ( fd_table[i].fd == fd ) {
fd_table[i].frozen = 0; fd_table[i].frozen = 0;
/*fprintf (stderr, "** FD %d thawed\n", fd );*/ DEBUG1 ("fd %d thawed", fd );
break; break;
} }
} }