PLEASE TEST: New implementation of blocking socket I/O

Corinna Vinschen
Thu Apr 1 10:38:00 GMT 2004

On Mar 31 22:06, Pierre A. Humblet wrote:
> At 05:36 PM 3/31/2004 +0200, Corinna Vinschen wrote:
> >There's a chance that the first call to WSAwhatever already returns
> >WSAEWOULDBLOCK and ret is uninitialized.  I've applied a fix which
> >always set ret to 0 in calls to WSAwhatever.  Does that help?
> It makes a difference, but I am not sure why, it shouldn't be necessary

When calling WSASendTo for the first time, ret was uninitialized.  If
WSASendTo returns with WSAEWOULDBLOCK and ret hasn't been touched, the
weird result could have occured.  But you're right.  In theory, WSASendTo
should always set ret to a useful value.  In theory...

> At least I more or less consistently saw:
>   264 5385988 [main] cvs 91960353 __set_errno: void
> __set_winsock_errno(const char*, int):366 val 1
>   154 5386142 [main] cvs 91960353 __set_winsock_errno: sendmsg:1100 -
> winsock error 6 -> errno 1
> When stepping through the code I noticed that wsock_event::release
> was calling WSACloseEvent. Later the wsock_event destructor was calling
> WSACloseEvent again, setting the wsock errno. So I fixed that, moving both
> wsock_event::release and the destructor out of the way (in a crude way),
> so as not to affect the wsock errno.

Thanks for catching.  I've checked in a patch to wsock_event::release
which saves the last error and restores it at the end, if not ioctlsocket
fails, in which case I return that error.  I'm not quite sure if that's
exactly right but I think the ioctlsocket error would have some weight.
I also removed the destructor entirely.

> Then I started seeing
>   279 3295264 [main] cvs 295057 writev: 1024 = write (3, 0x7DE7E0, 1), errno 2
>   344 3295608 [main] cvs 295057 sig_dispatch_pending: exit_state 0, cur
> thread id 0xFFF0A123, sigtid 0xFFEF130B, 0x0
>   188 3295796 [main] cvs 295057 writev: writev (3, 0x7DE810, 1)
>   433 3296229 [main] cvs 295057 __set_errno: void __set_winsock_errno(const
> char*, int):367 val 0
>   209 3296438 [main] cvs 295057 __set_winsock_errno: sendmsg:1102 - winsock
> error 0 -> errno 0
> i.e. it fails but winsock_errno is 0. I made a couple more changes in
> wsock_event::wait where the code could wipe out the wsock_errno (see patches).

I've applied a patch to wsock_event::wait to take a failing
WSAEnumNetworkEvents into account and yes, you're right, the memset is
not needed since WSAEnumNetworkEvents actually copies an internal
datatstructure into the address given as parameter.

I've also applied the following:  If the FD_CLOSE event is recognized,
then ret is set to 0 only if wsa_err is still 0.  Otherwise it would
have been possible that even in case an error has happened, the function
returns 0.

> No luck, wsock errno is still 0, but sendmsg surely fails.


> And yes, from time to time it does like in my first report, hanging
>   158 2552618 [main] cvs 540017 readv: readv (4, 0x7DEBC0, 1) blocking,
> sigcatchers 6
>   154 2552772 [main] cvs 540017 readv: no need to call ready_for_read

Hmm 2.  That really stumps me.  Is it possible that WSARecvFrom receives
partial data, sets ret to a vaue > 0 and nevertheless returns WSAEWOULDBLOCK?
That sounds unbelievable.

> Perhaps you would have more luck triggering this bug if
> you tried a low speed (modem) connection.

I don't even own a modem.

Thanks for debugging, btw.  However, I'm wondering if I should revert
to overlapped I/O.  While the async I/O code looks pretty simple, it
seems I opened the box of Pandora.  Sigh.


Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Developer                      
Red Hat, Inc.

More information about the Cygwin-developers mailing list