Fix hang in socket closing.

* src/w32-io.c (destroy_reader): Call shutdown.
(reader): Do not print an error in the shutdown case.
This commit is contained in:
Werner Koch 2013-04-25 12:00:16 +01:00
parent 2118f49701
commit 9f330be821

View File

@ -316,6 +316,21 @@ reader (void *arg)
} }
else 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; ctx->error = 1;
TRACE_LOG1 ("recv error: ec=%d", ctx->error_code); TRACE_LOG1 ("recv error: ec=%d", ctx->error_code);
} }
@ -357,6 +372,7 @@ reader (void *arg)
UNLOCK (ctx->mutex); UNLOCK (ctx->mutex);
break; break;
} }
TRACE_LOG1 ("got %u bytes", nread); TRACE_LOG1 ("got %u bytes", nread);
ctx->writepos = (ctx->writepos + nread) % READBUF_SIZE; ctx->writepos = (ctx->writepos + nread) % READBUF_SIZE;
@ -495,6 +511,26 @@ destroy_reader (struct reader_context_s *ctx)
} }
#endif #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, TRACE1 (DEBUG_SYSIO, "gpgme:destroy_reader", ctx->file_hd,
"waiting for termination of thread %p", ctx->thread_hd); "waiting for termination of thread %p", ctx->thread_hd);
WaitForSingleObject (ctx->stopped, INFINITE); WaitForSingleObject (ctx->stopped, INFINITE);