aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2013-04-25 11:00:16 +0000
committerWerner Koch <[email protected]>2013-05-08 18:38:50 +0000
commit9f330be8210d2498fe93d4166b6f6c02fca76475 (patch)
tree1874cdd0303cacfc7afa3ec77d397939a70162a1
parentImprove debug output of the I/O reader and writer. (diff)
downloadgpgme-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.c36
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);