diff --git a/src/w32-io.c b/src/w32-io.c index 776e3792..d896ec0e 100644 --- a/src/w32-io.c +++ b/src/w32-io.c @@ -162,7 +162,9 @@ struct reader_context_s HANDLE have_data_ev; /* This is automatically reset. */ HANDLE have_space_ev; - HANDLE stopped; + /* This is manually reset but actually only triggered once. */ + HANDLE close_ev; + size_t readpos, writepos; char buffer[READBUF_SIZE]; }; @@ -194,7 +196,7 @@ struct writer_context_s /* This is manually reset. */ HANDLE have_data; HANDLE is_empty; - HANDLE stopped; + HANDLE close_ev; size_t nbytes; char buffer[WRITEBUF_SIZE]; }; @@ -383,9 +385,18 @@ reader (void *arg) } /* Indicate that we have an error or EOF. */ if (!SetEvent (ctx->have_data_ev)) - TRACE_LOG2 ("SetEvent (0x%x) failed: ec=%d", ctx->have_data_ev, - (int) GetLastError ()); - SetEvent (ctx->stopped); + TRACE_LOG2 ("SetEvent (0x%x) failed: ec=%d", ctx->have_data_ev, + (int) GetLastError ()); + + TRACE_LOG ("waiting for close"); + WaitForSingleObject (ctx->close_ev, INFINITE); + + CloseHandle (ctx->close_ev); + CloseHandle (ctx->have_data_ev); + CloseHandle (ctx->have_space_ev); + CloseHandle (ctx->thread_hd); + DESTROY_LOCK (ctx->mutex); + free (ctx); return TRACE_SUC (); } @@ -427,16 +438,16 @@ create_reader (int fd) if (ctx->have_data_ev) ctx->have_space_ev = CreateEvent (&sec_attr, FALSE, TRUE, NULL); if (ctx->have_space_ev) - ctx->stopped = CreateEvent (&sec_attr, TRUE, FALSE, NULL); - if (!ctx->have_data_ev || !ctx->have_space_ev || !ctx->stopped) + ctx->close_ev = CreateEvent (&sec_attr, TRUE, FALSE, NULL); + if (!ctx->have_data_ev || !ctx->have_space_ev || !ctx->close_ev) { TRACE_LOG1 ("CreateEvent failed: ec=%d", (int) GetLastError ()); if (ctx->have_data_ev) CloseHandle (ctx->have_data_ev); if (ctx->have_space_ev) CloseHandle (ctx->have_space_ev); - if (ctx->stopped) - CloseHandle (ctx->stopped); + if (ctx->close_ev) + CloseHandle (ctx->close_ev); free (ctx); /* FIXME: Translate the error code. */ TRACE_SYSERR (EIO); @@ -461,8 +472,8 @@ create_reader (int fd) CloseHandle (ctx->have_data_ev); if (ctx->have_space_ev) CloseHandle (ctx->have_space_ev); - if (ctx->stopped) - CloseHandle (ctx->stopped); + if (ctx->close_ev) + CloseHandle (ctx->close_ev); free (ctx); TRACE_SYSERR (EIO); return NULL; @@ -480,6 +491,9 @@ create_reader (int fd) } +/* Prepare destruction of the reader thread for CTX. Returns 0 if a + call to this function is sufficient and destroy_reader_finish shall + not be called. */ static void destroy_reader (struct reader_context_s *ctx) { @@ -531,24 +545,12 @@ destroy_reader (struct reader_context_s *ctx) ctx->file_sock, (int) WSAGetLastError ()); } - TRACE1 (DEBUG_SYSIO, "gpgme:destroy_reader", ctx->file_hd, - "waiting for termination of thread %p", ctx->thread_hd); - WaitForSingleObject (ctx->stopped, INFINITE); - TRACE1 (DEBUG_SYSIO, "gpgme:destroy_reader", ctx->file_hd, - "thread %p has terminated", ctx->thread_hd); - - if (ctx->stopped) - CloseHandle (ctx->stopped); - if (ctx->have_data_ev) - CloseHandle (ctx->have_data_ev); - if (ctx->have_space_ev) - CloseHandle (ctx->have_space_ev); - CloseHandle (ctx->thread_hd); - DESTROY_LOCK (ctx->mutex); - free (ctx); + /* After setting this event CTX is void. */ + SetEvent (ctx->close_ev); } + /* Find a reader context or create a new one. Note that the reader context will last until a _gpgme_io_close. */ static struct reader_context_s * @@ -585,26 +587,6 @@ find_reader (int fd, int start_it) } -static void -kill_reader (int fd) -{ - int i; - - LOCK (reader_table_lock); - for (i = 0; i < reader_table_size; i++) - { - if (reader_table[i].used && reader_table[i].fd == fd) - { - destroy_reader (reader_table[i].context); - reader_table[i].context = NULL; - reader_table[i].used = 0; - break; - } - } - UNLOCK (reader_table_lock); -} - - int _gpgme_io_read (int fd, void *buffer, size_t count) { @@ -774,7 +756,16 @@ writer (void *arg) /* Indicate that we have an error. */ if (!SetEvent (ctx->is_empty)) TRACE_LOG1 ("SetEvent failed: ec=%d", (int) GetLastError ()); - SetEvent (ctx->stopped); + + TRACE_LOG ("waiting for close"); + WaitForSingleObject (ctx->close_ev, INFINITE); + + CloseHandle (ctx->close_ev); + CloseHandle (ctx->have_data); + CloseHandle (ctx->is_empty); + CloseHandle (ctx->thread_hd); + DESTROY_LOCK (ctx->mutex); + free (ctx); return TRACE_SUC (); } @@ -816,16 +807,16 @@ create_writer (int fd) if (ctx->have_data) ctx->is_empty = CreateEvent (&sec_attr, TRUE, TRUE, NULL); if (ctx->is_empty) - ctx->stopped = CreateEvent (&sec_attr, TRUE, FALSE, NULL); - if (!ctx->have_data || !ctx->is_empty || !ctx->stopped) + ctx->close_ev = CreateEvent (&sec_attr, TRUE, FALSE, NULL); + if (!ctx->have_data || !ctx->is_empty || !ctx->close_ev) { TRACE_LOG1 ("CreateEvent failed: ec=%d", (int) GetLastError ()); if (ctx->have_data) CloseHandle (ctx->have_data); if (ctx->is_empty) CloseHandle (ctx->is_empty); - if (ctx->stopped) - CloseHandle (ctx->stopped); + if (ctx->close_ev) + CloseHandle (ctx->close_ev); free (ctx); /* FIXME: Translate the error code. */ TRACE_SYSERR (EIO); @@ -850,8 +841,8 @@ create_writer (int fd) CloseHandle (ctx->have_data); if (ctx->is_empty) CloseHandle (ctx->is_empty); - if (ctx->stopped) - CloseHandle (ctx->stopped); + if (ctx->close_ev) + CloseHandle (ctx->close_ev); free (ctx); TRACE_SYSERR (EIO); return NULL; @@ -868,6 +859,7 @@ create_writer (int fd) return ctx; } + static void destroy_writer (struct writer_context_s *ctx) { @@ -897,21 +889,8 @@ destroy_writer (struct writer_context_s *ctx) } #endif - TRACE1 (DEBUG_SYSIO, "gpgme:destroy_writer", ctx->file_hd, - "waiting for termination of thread %p", ctx->thread_hd); - WaitForSingleObject (ctx->stopped, INFINITE); - TRACE1 (DEBUG_SYSIO, "gpgme:destroy_writer", ctx->file_hd, - "thread %p has terminated", ctx->thread_hd); - - if (ctx->stopped) - CloseHandle (ctx->stopped); - if (ctx->have_data) - CloseHandle (ctx->have_data); - if (ctx->is_empty) - CloseHandle (ctx->is_empty); - CloseHandle (ctx->thread_hd); - DESTROY_LOCK (ctx->mutex); - free (ctx); + /* After setting this event CTX is void. */ + SetEvent (ctx->close_ev); } @@ -951,26 +930,6 @@ find_writer (int fd, int start_it) } -static void -kill_writer (int fd) -{ - int i; - - LOCK (writer_table_lock); - for (i = 0; i < writer_table_size; i++) - { - if (writer_table[i].used && writer_table[i].fd == fd) - { - destroy_writer (writer_table[i].context); - writer_table[i].context = NULL; - writer_table[i].used = 0; - break; - } - } - UNLOCK (writer_table_lock); -} - - int _gpgme_io_write (int fd, const void *buffer, size_t count) { @@ -1195,8 +1154,32 @@ _gpgme_io_close (int fd) fd, fd_table[fd].handle, fd_table[fd].socket, fd_table[fd].dup_from); - kill_reader (fd); - kill_writer (fd); + LOCK (reader_table_lock); + for (i = 0; i < reader_table_size; i++) + { + if (reader_table[i].used && reader_table[i].fd == fd) + { + destroy_reader (reader_table[i].context); + reader_table[i].context = NULL; + reader_table[i].used = 0; + break; + } + } + UNLOCK (reader_table_lock); + + LOCK (writer_table_lock); + for (i = 0; i < writer_table_size; i++) + { + if (writer_table[i].used && writer_table[i].fd == fd) + { + destroy_writer (writer_table[i].context); + writer_table[i].context = NULL; + writer_table[i].used = 0; + break; + } + } + UNLOCK (writer_table_lock); + LOCK (notify_table_lock); for (i = 0; i < DIM (notify_table); i++) {