[PATCH] Fix poll/select signal socket as write ready on connect failure
Corinna Vinschen
corinna-cygwin@cygwin.com
Fri Jul 17 19:21:40 GMT 2020
Hi Marc,
On Jul 17 20:56, Marc Hoersken via Cygwin wrote:
> Hi Corinna,
>
> Am 16.07.2020 um 11:25 schrieb Corinna Vinschen:
> [...]
> > So, rather than setting FD_WRITE at some later point in the code, what
> > about handling this where the other FD_CONNECT stuff is handled, by
> > not erasing the FD_CONNECT bit, just like with FD_CLOSE?
>
> I think this makes more sense, yes. I am just not sure if the socket should
> also be write ready in case of a socket error. Looking at the description of
> EINPROGRESS on the man page of connect [1], it seems like writability is
> given regardless of the connection being successful or not, but as soon as
> the connection attempt is no longer pending. For successful connections
> FD_WRITE will be given already, so we will only need to set it for failed
> connections regardless of a socket error in wsock_events->connect_errorcode.
> Therefore I suggest to move the line setting FD_WRITE [2] one level up
> outside of the else branch.
Sounds right to me.
> [...]
> I already tested your diff successfully, so this could be an alternative
> approach to the issue. I just think the wsock_events->connect_errorcode
> should also only be reset if FD_CONNECT is removed, right? So the if branch
> would need to be extended to include the second line [3] as well.
I don't agree here. The sole purpose for connect_errorcode is to set
SOL_SOCKET/SO_ERROR in case a caller requests FD_CONNECT and FD_CONNECT
is available. After being set once, SOL_SOCKET/SO_ERROR should not be
rewritten, given the description of SO_ERROR in `man 7 socket':
SO_ERROR
Get and clear the pending socket error. This socket option is
^^^^^^^^^
read-only. Expects an integer.
Therefore I'm inclined to push this:
diff --git a/winsup/cygwin/fhandler_socket_inet.cc b/winsup/cygwin/fhandler_socket_inet.cc
index e5b0d2d1443e..2b50671e533d 100644
--- a/winsup/cygwin/fhandler_socket_inet.cc
+++ b/winsup/cygwin/fhandler_socket_inet.cc
@@ -352,9 +352,13 @@ fhandler_socket_wsock::evaluate_events (const long event_mask, long &events,
WSASetLastError (wsa_err);
ret = SOCKET_ERROR;
}
- else
- wsock_events->events |= FD_WRITE;
- wsock_events->events &= ~FD_CONNECT;
+ /* Since FD_CONNECT is only given once, we have to keep FD_CONNECT
+ for connection failed sockets to have consistent behaviour in
+ programs calling poll/select multiple times. Example test to
+ non-listening port: curl -v 127.0.0.1:47 */
+ if (connect_state () != connect_failed)
+ wsock_events->events &= ~FD_CONNECT;
+ wsock_events->events |= FD_WRITE;
wsock_events->connect_errorcode = 0;
}
/* This test makes accept/connect behave as on Linux when accept/connect
@@ -376,12 +380,6 @@ fhandler_socket_wsock::evaluate_events (const long event_mask, long &events,
if (erase)
wsock_events->events &= ~(events & ~(FD_WRITE | FD_CLOSE));
}
- /* Since FD_CONNECT is only given once, we manually need to set
- FD_WRITE for connection failed sockets to have consistent
- behaviour in programs calling poll/select multiple times.
- Example test to non-listening port: curl -v 127.0.0.1:47 */
- if ((connect_state () == connect_failed) && (event_mask & FD_WRITE))
- wsock_events->events |= FD_WRITE;
UNLOCK_EVENTS;
return ret;
Make sense?
Thanks,
Corinna
--
Corinna Vinschen
Cygwin Maintainer
More information about the Cygwin
mailing list