aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2014-11-07 16:20:19 +0000
committerWerner Koch <[email protected]>2014-11-07 16:20:19 +0000
commit1023508f210cd136992661c01b55b428de86a182 (patch)
tree95c6a0920e0a0a6d6cd0b47c3adc16929f72d17b
parentPost release updates (diff)
downloadlibassuan-1023508f210cd136992661c01b55b428de86a182.tar.gz
libassuan-1023508f210cd136992661c01b55b428de86a182.zip
w32: Remove I/O delays due to our 100ms delay after an EAGAIN.
* src/system-w32.c (__assuan_read): Retry using select. Map WSAECONNRESET to EPIPE. (__assuan_write): Retry using select. * src/assuan-buffer.c (readline) [W32]: Return EOF instead of EPIPE.
-rw-r--r--src/assuan-buffer.c9
-rw-r--r--src/system-w32.c37
2 files changed, 46 insertions, 0 deletions
diff --git a/src/assuan-buffer.c b/src/assuan-buffer.c
index f2238e7..04aff5a 100644
--- a/src/assuan-buffer.c
+++ b/src/assuan-buffer.c
@@ -80,6 +80,15 @@ readline (assuan_context_t ctx, char *buf, size_t buflen,
{
if (errno == EINTR)
continue;
+#ifdef HAVE_W32_SYSTEM
+ if (errno == EPIPE)
+ {
+ /* Under Windows we get EPIPE (actually ECONNRESET)
+ after termination of the client. Assume an EOF. */
+ *r_eof = 1;
+ break; /* allow incomplete lines */
+ }
+#endif /*HAVE_W32_SYSTEM*/
return -1; /* read error */
}
else if (!n)
diff --git a/src/system-w32.c b/src/system-w32.c
index 3ee5359..85b8fa8 100644
--- a/src/system-w32.c
+++ b/src/system-w32.c
@@ -197,9 +197,27 @@ __assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
if (is_socket (fd))
{
+ int tries = 3;
+
+ again:
+ ec = 0;
res = recv (HANDLE2SOCKET (fd), buffer, size, 0);
if (res == -1)
ec = WSAGetLastError ();
+ if (ec == WSAEWOULDBLOCK && tries--)
+ {
+ /* EAGAIN: Use select to wait for resources and try again.
+ We do this 3 times and then give up. The higher level
+ layer then needs to take care of EAGAIN. No need to
+ specify a timeout - the socket is not expected to be in
+ blocking mode. */
+ fd_set fds;
+
+ FD_ZERO (&fds);
+ FD_SET (HANDLE2SOCKET (fd), &fds);
+ select (0, &fds, NULL, NULL, NULL);
+ goto again;
+ }
}
else
{
@@ -224,6 +242,7 @@ __assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
gpg_err_set_errno (EAGAIN);
break;
+ case WSAECONNRESET: /* Due to the use of recv. */
case ERROR_BROKEN_PIPE:
gpg_err_set_errno (EPIPE);
break;
@@ -247,9 +266,27 @@ __assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer,
if (is_socket (fd))
{
+ int tries = 3;
+
+ again:
+ ec = 0;
res = send (HANDLE2SOCKET (fd), buffer, size, 0);
if (res == -1)
ec = WSAGetLastError ();
+ if (ec == WSAEWOULDBLOCK && tries--)
+ {
+ /* EAGAIN: Use select to wait for resources and try again.
+ We do this 3 times and then give up. The higher level
+ layer then needs to take care of EAGAIN. No need to
+ specify a timeout - the socket is not expected to be in
+ blocking mode. */
+ fd_set fds;
+
+ FD_ZERO (&fds);
+ FD_SET (HANDLE2SOCKET (fd), &fds);
+ select (0, NULL, &fds, NULL, NULL);
+ goto again;
+ }
}
else
{