This is the mail archive of the mailing list for the Cygwin project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Winsock recv/WSARecv(..., MSG_PEEK) is unreliable (was Re: Transient fetchmail ...)

On Wed, Aug 08, 2001 at 11:01:00PM -0400, Jason Tishler wrote:
> Thanks for trying to help me, it is much appreciated.  Unfortunately,
> your problem seems to be similar to (or the same as) Olaf's.  Your
> problem seems to be on the transmit side -- mine seems to be on the
> receive side.

I believe that I have finally found the root cause to my transient
fetchmail corruption problems under Windows 2000.  From the following
MSDN articles, it appears the Winsock's recv/WSARecv(..., MSG_PEEK)
is inherently unreliable and strongly discouraged:

The following fetchmail code is affected by the above:

    int SockRead(int sock, char *buf, int len)
        char *bp = buf;
            if ((n = recv(sock, bp, len, MSG_PEEK)) <= 0)
                return (-1);
            if ((newline = memchr(bp, '\n', n)) != NULL)
                n = newline - bp + 1;           // *** [1] ***
            if ((n = read(sock, bp, n)) == -1)  // *** [2] ***
                return (-1);
            bp += n;
        while (!newline && len);
        *bp = '\0';

The number of bytes read in [2] is occasionally less than the number of
bytes requested as determined by [1].  This causes fetchmail to put null
characters in the wrong place and to read the same bytes more than once.
This is the source of the "corruption" that I have been experiencing
under 2000.  For some reason, this problem has not occurred (yet) under
NT 4.0 SP5/SP6a.

Is there any way to fix this in Cygwin?  Otherwise, other applications
that use MSG_PEEK may fail in similar ways.

The attached *ugly* patch to fetchmail works around this problem.  If
the MSG_PEEK problem cannot be fixed in Cygwin, then what is the best
way to solve this issue in fetchmail?  I see the following options:

1. Leverage off of existing BeOS specific code that does not use MSG_PEEK
but only reads one byte at a time.

2. Rework the ugly patch with __CYGWIN__ #ifdefs.

3. Rework SockRead() to not use MSG_PEEK, but instead "drain data
immediately upon arrival into application-allocated buffer space" as
suggested by the MSDN.

I guess that have I ordered the above in what I think is decreasing
chance of acceptance into fetchmail CVS.

Does anyone have any other, hopefully better, ideas?

--- socket.c.orig	Tue Aug 14 10:36:19 2001
+++ socket.c	Tue Aug 14 10:38:06 2001
@@ -493,7 +493,7 @@ int SockWrite(int sock, char *buf, int l
 int SockRead(int sock, char *buf, int len)
     char *newline, *bp = buf;
-    int n;
+    int n, n2, n3;
 #ifdef	SSL_ENABLE
     SSL *ssl;
@@ -578,8 +578,15 @@ int SockRead(int sock, char *buf, int le
 	if ((newline = memchr(bp, '\n', n)) != NULL)
 	    n = newline - bp + 1;
 #ifndef __BEOS__
-	if ((n = fm_read(sock, bp, n)) == -1)
+	if ((n2 = fm_read(sock, bp, n)) == -1)
+	if (n2 != n)
+	{
+	    if ((n3 = fm_read(sock, bp + n2, n - n2)) == -1)
+		return(-1);
+	    printf("n = %d, n2 = %d, n3 = %d\n", n, n2, n3);
+	}
 #endif /* __BEOS__ */
 	bp += n;

Unsubscribe info:
Bug reporting:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]