2828# define ECONNREFUSED WSAECONNREFUSED
2929# undef EWOULDBLOCK
3030# define EWOULDBLOCK WSAEWOULDBLOCK
31+ # undef EINPROGRESS
32+ # define EINPROGRESS WSAEINPROGRESS
3133# ifdef EINTR
3234# undef EINTR
3335# endif
@@ -550,8 +552,6 @@ channel_open(
550552#else
551553 int port = port_in ;
552554 struct timeval start_tv ;
553- int so_error ;
554- socklen_t so_error_len = sizeof (so_error );
555555#endif
556556 channel_T * channel ;
557557 int ret ;
@@ -633,7 +633,6 @@ channel_open(
633633 {
634634 if (errno != EWOULDBLOCK
635635 && errno != ECONNREFUSED
636-
637636#ifdef EINPROGRESS
638637 && errno != EINPROGRESS
639638#endif
@@ -653,14 +652,13 @@ channel_open(
653652 if (waittime >= 0 && ret < 0 )
654653 {
655654 struct timeval tv ;
655+ fd_set rfds ;
656656 fd_set wfds ;
657- #if defined(__APPLE__ ) && __APPLE__ == 1
658- # define PASS_RFDS
659- fd_set rfds ;
657+ int so_error = 0 ;
658+ socklen_t so_error_len = sizeof (so_error );
660659
661660 FD_ZERO (& rfds );
662661 FD_SET (sd , & rfds );
663- #endif
664662 FD_ZERO (& wfds );
665663 FD_SET (sd , & wfds );
666664
@@ -671,13 +669,7 @@ channel_open(
671669#endif
672670 ch_logn (channel ,
673671 "Waiting for connection (waittime %d msec)..." , waittime );
674- ret = select ((int )sd + 1 ,
675- #ifdef PASS_RFDS
676- & rfds ,
677- #else
678- NULL ,
679- #endif
680- & wfds , NULL , & tv );
672+ ret = select ((int )sd + 1 , & rfds , & wfds , NULL , & tv );
681673
682674 if (ret < 0 )
683675 {
@@ -689,30 +681,39 @@ channel_open(
689681 channel_free (channel );
690682 return NULL ;
691683 }
692- #ifdef PASS_RFDS
693- if (ret == 0 && FD_ISSET (sd , & rfds ) && FD_ISSET (sd , & wfds ))
694- {
695- /* For OS X, this implies error. See tcp(4). */
696- ch_error (channel , "channel_open: Connect failed" );
697- EMSG (_ (e_cannot_connect ));
698- sock_close (sd );
699- channel_free (channel );
700- return NULL ;
701- }
702- #endif
703- #ifdef WIN32
704- /* On Win32 select() is expected to work and wait for up to the
705- * waittime for the socket to be open. */
706- if (!FD_ISSET (sd , & wfds ) || ret == 0 )
707- #else
708- /* See socket(7) for the behavior on Linux-like systems:
684+
685+ /* On Win32: select() is expected to work and wait for up to the
686+ * waittime for the socket to be open.
687+ * On Linux-like systems: See socket(7) for the behavior
709688 * After putting the socket in non-blocking mode, connect() will
710689 * return EINPROGRESS, select() will not wait (as if writing is
711690 * possible), need to use getsockopt() to check if the socket is
712- * actually open. */
713- getsockopt (sd , SOL_SOCKET , SO_ERROR , & so_error , & so_error_len );
714- if (!FD_ISSET (sd , & wfds ) || ret == 0 || so_error != 0 )
691+ * actually connect.
692+ * We detect an failure to connect when both read and write fds
693+ * are set. Use getsockopt() to find out what kind of failure. */
694+ if (FD_ISSET (sd , & rfds ) && FD_ISSET (sd , & wfds ))
695+ {
696+ ret = getsockopt (sd ,
697+ SOL_SOCKET , SO_ERROR , & so_error , & so_error_len );
698+ if (ret < 0 || (so_error != 0
699+ && so_error != EWOULDBLOCK
700+ && so_error != ECONNREFUSED
701+ #ifdef EINPROGRESS
702+ && so_error != EINPROGRESS
715703#endif
704+ ))
705+ {
706+ ch_errorn (channel ,
707+ "channel_open: Connect failed with errno %d" ,
708+ so_error );
709+ PERROR (_ (e_cannot_connect ));
710+ sock_close (sd );
711+ channel_free (channel );
712+ return NULL ;
713+ }
714+ }
715+
716+ if (!FD_ISSET (sd , & wfds ) || so_error != 0 )
716717 {
717718#ifndef WIN32
718719 struct timeval end_tv ;
0 commit comments