Can somebody pinch me, please?
Fri Mar 11 16:19:00 GMT 2005
Corinna Vinschen wrote:
> While I was brooding over the mysterious ssh-add/ssh-agent hang, I
> suddenly came across these fairly old lines in fhandler_socket::accept():
> if ((SOCKET) res == INVALID_SOCKET && WSAGetLastError () == WSAEWOULDBLOCK)
> in_progress = true;
> Then, in case of unix stream sockets, the secret event stuff and the
> new eid credential transaction is called.
> Looks good...
> Hang on...
> What the heck is an accept in progress?!? I mean, I understand a
> non-blocking connect in progress which returns EWOULDBLOCK, but an
> accept in progress? What would be returned in the sockaddr parameter
> if the return code is -1? That doesn't make sense.
> After months of asceticism I had another look into the SUSv3 and MSDN
> man pages of accept
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/accept_2.asp (*)
> and it turns out that returning -1 and an error of (WSA)EWOULDBLOCK
> indicate that a non-blocking accept has simply nothing to accept!
> So there is nobody knocking on the door (==connecting), which means,
> calling any secret event or eip credential transaction is rightout
> wrong. Right?
> I was going to apply the below patch. I can confirm that ssh and (sigh)
> ssh-agent/ssh-add still work for me (all are using non-blocking sockets),
> but somehow I need a bit of shoulder patting before doing this.
> Does anybody have problems or can imagine problems with this patch?
> It just removes all in_progress handling from unix stream sockets, so
> that the secret event and eid credential transactions only take place if
> actually a socket connection has been accepted.
Well, i guess i can try to remember why this code was added. Maybe i'm
misguided here. SUSv2 states on connect() that
If the connection cannot be established immediately and O_NONBLOCK is
set for the file descriptor for the socket, connect() will fail and set
errno to [EINPROGRESS], but the connection request will not be aborted,
and the connection will be established asynchronously. Subsequent calls
to connect() for the same socket, before the connection is established,
will fail and set errno to [EALREADY].
I was probably assuming that there's some kind of "symmetry" between
connect() and accept() here. That is, when server accepts()s on
non-blocking socket and there's no inbound requests available it's still
possible that after some time client tries to connect() and will
succeed. At this time, it will need server-side secret event in place to
complete connection. I see now that there's nothing about asynchronous
accept() on non-blocking socket. You're right that in such case it's not
possible to determine peer's address. Yet i'd like to check what
winsock's connect() will return on win32 machine when trying to connect
to socket() on which accept() failed with EWOULDBLOCK on server side.
I'll take a grab on windows machine this weekend and test.
More information about the Cygwin-developers