comparison src/channel.c @ 8330:ec940c11f749 v7.4.1457

commit https://github.com/vim/vim/commit/d42119fff228434fe57e88d501c744de0a9fb1b1 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Feb 28 20:51:49 2016 +0100 patch 7.4.1457 Problem: Opening a channel with select() is not done properly. Solution: Also used read-fds. Use getsockopt() to check for errors. (Ozaki Kiichi)
author Christian Brabandt <cb@256bit.org>
date Sun, 28 Feb 2016 21:00:04 +0100
parents e2021d6feeda
children 07713b8243ac
comparison
equal deleted inserted replaced
8329:105cfd08008e 8330:ec940c11f749
26 # define SOCK_ERRNO errno = WSAGetLastError() 26 # define SOCK_ERRNO errno = WSAGetLastError()
27 # undef ECONNREFUSED 27 # undef ECONNREFUSED
28 # define ECONNREFUSED WSAECONNREFUSED 28 # define ECONNREFUSED WSAECONNREFUSED
29 # undef EWOULDBLOCK 29 # undef EWOULDBLOCK
30 # define EWOULDBLOCK WSAEWOULDBLOCK 30 # define EWOULDBLOCK WSAEWOULDBLOCK
31 # undef EINPROGRESS
32 # define EINPROGRESS WSAEINPROGRESS
31 # ifdef EINTR 33 # ifdef EINTR
32 # undef EINTR 34 # undef EINTR
33 # endif 35 # endif
34 # define EINTR WSAEINTR 36 # define EINTR WSAEINTR
35 # define sock_write(sd, buf, len) send((SOCKET)sd, buf, len, 0) 37 # define sock_write(sd, buf, len) send((SOCKET)sd, buf, len, 0)
548 u_short port = port_in; 550 u_short port = port_in;
549 u_long val = 1; 551 u_long val = 1;
550 #else 552 #else
551 int port = port_in; 553 int port = port_in;
552 struct timeval start_tv; 554 struct timeval start_tv;
553 int so_error;
554 socklen_t so_error_len = sizeof(so_error);
555 #endif 555 #endif
556 channel_T *channel; 556 channel_T *channel;
557 int ret; 557 int ret;
558 558
559 #ifdef WIN32 559 #ifdef WIN32
631 SOCK_ERRNO; 631 SOCK_ERRNO;
632 if (ret < 0) 632 if (ret < 0)
633 { 633 {
634 if (errno != EWOULDBLOCK 634 if (errno != EWOULDBLOCK
635 && errno != ECONNREFUSED 635 && errno != ECONNREFUSED
636
637 #ifdef EINPROGRESS 636 #ifdef EINPROGRESS
638 && errno != EINPROGRESS 637 && errno != EINPROGRESS
639 #endif 638 #endif
640 ) 639 )
641 { 640 {
651 /* If we don't block and connect() failed then try using select() to 650 /* If we don't block and connect() failed then try using select() to
652 * wait for the connection to be made. */ 651 * wait for the connection to be made. */
653 if (waittime >= 0 && ret < 0) 652 if (waittime >= 0 && ret < 0)
654 { 653 {
655 struct timeval tv; 654 struct timeval tv;
655 fd_set rfds;
656 fd_set wfds; 656 fd_set wfds;
657 #if defined(__APPLE__) && __APPLE__ == 1 657 int so_error = 0;
658 # define PASS_RFDS 658 socklen_t so_error_len = sizeof(so_error);
659 fd_set rfds;
660 659
661 FD_ZERO(&rfds); 660 FD_ZERO(&rfds);
662 FD_SET(sd, &rfds); 661 FD_SET(sd, &rfds);
663 #endif
664 FD_ZERO(&wfds); 662 FD_ZERO(&wfds);
665 FD_SET(sd, &wfds); 663 FD_SET(sd, &wfds);
666 664
667 tv.tv_sec = waittime / 1000; 665 tv.tv_sec = waittime / 1000;
668 tv.tv_usec = (waittime % 1000) * 1000; 666 tv.tv_usec = (waittime % 1000) * 1000;
669 #ifndef WIN32 667 #ifndef WIN32
670 gettimeofday(&start_tv, NULL); 668 gettimeofday(&start_tv, NULL);
671 #endif 669 #endif
672 ch_logn(channel, 670 ch_logn(channel,
673 "Waiting for connection (waittime %d msec)...", waittime); 671 "Waiting for connection (waittime %d msec)...", waittime);
674 ret = select((int)sd + 1, 672 ret = select((int)sd + 1, &rfds, &wfds, NULL, &tv);
675 #ifdef PASS_RFDS
676 &rfds,
677 #else
678 NULL,
679 #endif
680 &wfds, NULL, &tv);
681 673
682 if (ret < 0) 674 if (ret < 0)
683 { 675 {
684 SOCK_ERRNO; 676 SOCK_ERRNO;
685 ch_errorn(channel, 677 ch_errorn(channel,
687 PERROR(_(e_cannot_connect)); 679 PERROR(_(e_cannot_connect));
688 sock_close(sd); 680 sock_close(sd);
689 channel_free(channel); 681 channel_free(channel);
690 return NULL; 682 return NULL;
691 } 683 }
692 #ifdef PASS_RFDS 684
693 if (ret == 0 && FD_ISSET(sd, &rfds) && FD_ISSET(sd, &wfds)) 685 /* On Win32: select() is expected to work and wait for up to the
694 { 686 * waittime for the socket to be open.
695 /* For OS X, this implies error. See tcp(4). */ 687 * On Linux-like systems: See socket(7) for the behavior
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:
709 * After putting the socket in non-blocking mode, connect() will 688 * After putting the socket in non-blocking mode, connect() will
710 * return EINPROGRESS, select() will not wait (as if writing is 689 * return EINPROGRESS, select() will not wait (as if writing is
711 * possible), need to use getsockopt() to check if the socket is 690 * possible), need to use getsockopt() to check if the socket is
712 * actually open. */ 691 * actually connect.
713 getsockopt(sd, SOL_SOCKET, SO_ERROR, &so_error, &so_error_len); 692 * We detect an failure to connect when both read and write fds
714 if (!FD_ISSET(sd, &wfds) || ret == 0 || so_error != 0) 693 * are set. Use getsockopt() to find out what kind of failure. */
715 #endif 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
703 #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)
716 { 717 {
717 #ifndef WIN32 718 #ifndef WIN32
718 struct timeval end_tv; 719 struct timeval end_tv;
719 long elapsed_msec; 720 long elapsed_msec;
720 721