This is the mail archive of the cygwin-developers@cygwin.com 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]
Other format: [Raw text]

Re: Can somebody pinch me, please?


Corinna Vinschen wrote:
Guys,

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.

Fine...

Looks good...

Well...

Hang on...

Erm...

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://www.opengroup.org/onlinepubs/009695399/functions/accept.html
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.

Anybody?

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.

egor.


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