diff options
author | Werner Koch <[email protected]> | 2013-04-25 11:00:16 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2013-05-08 18:38:50 +0000 |
commit | 9f330be8210d2498fe93d4166b6f6c02fca76475 (patch) | |
tree | 1874cdd0303cacfc7afa3ec77d397939a70162a1 | |
parent | Improve debug output of the I/O reader and writer. (diff) | |
download | gpgme-9f330be8210d2498fe93d4166b6f6c02fca76475.tar.gz gpgme-9f330be8210d2498fe93d4166b6f6c02fca76475.zip |
Fix hang in socket closing.
* src/w32-io.c (destroy_reader): Call shutdown.
(reader): Do not print an error in the shutdown case.
-rw-r--r-- | src/w32-io.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/src/w32-io.c b/src/w32-io.c index 164205e8..776e3792 100644 --- a/src/w32-io.c +++ b/src/w32-io.c @@ -316,6 +316,21 @@ reader (void *arg) } else { + /* Check whether the shutdown triggered the error - + no need to to print a warning in this case. */ + if ( ctx->error_code == WSAECONNABORTED + || ctx->error_code == WSAECONNRESET) + { + LOCK (ctx->mutex); + if (ctx->stop_me) + { + UNLOCK (ctx->mutex); + TRACE_LOG ("got shutdown"); + break; + } + UNLOCK (ctx->mutex); + } + ctx->error = 1; TRACE_LOG1 ("recv error: ec=%d", ctx->error_code); } @@ -357,6 +372,7 @@ reader (void *arg) UNLOCK (ctx->mutex); break; } + TRACE_LOG1 ("got %u bytes", nread); ctx->writepos = (ctx->writepos + nread) % READBUF_SIZE; @@ -495,6 +511,26 @@ destroy_reader (struct reader_context_s *ctx) } #endif + /* The reader thread is usually blocking in recv or ReadFile. If + the peer does not send an EOF or breaks the pipe the WFSO might + get stuck waiting for the termination of the reader thread. This + happens quite often with sockets, thus we definitely need to get + out of the recv. A shutdown does this nicely. For handles + (i.e. pipes) it would also be nice to cancel the operation, but + such a feature is only available since Vista. Thus we need to + dlopen that syscall. */ + if (ctx->file_hd != INVALID_HANDLE_VALUE) + { + /* Fixme: Call CancelSynchronousIo (handle_of_thread). */ + } + else if (ctx->file_sock != INVALID_SOCKET) + { + if (shutdown (ctx->file_sock, 2)) + TRACE2 (DEBUG_SYSIO, "gpgme:destroy_reader", ctx->file_hd, + "shutdown socket %d failed: %s", + 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); |