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

Jason Tishler jason@tishler.net
Tue Aug 14 10:51:00 GMT 2001


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:
 
    http://support.microsoft.com/support/kb/articles/Q192/5/99.ASP
    http://support.microsoft.com/support/kb/articles/Q140/2/63.asp

The following fetchmail code is affected by the above:

    int SockRead(int sock, char *buf, int len)
    {
        char *bp = buf;
        ...
        do
        {
            ...
            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?

Thanks,
Jason


More information about the Cygwin mailing list