* ext/socket/init.c (wait_connectable): fix error handling code.

RB_WAITFD_OUT is turned on even though an error occur.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31424 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
kosaki 2011-05-04 02:44:28 +00:00
Родитель 4da4cb0421
Коммит 9851b0ce2f
2 изменённых файлов: 33 добавлений и 8 удалений

Просмотреть файл

@ -1,3 +1,8 @@
Wed May 4 11:42:47 2011 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
* ext/socket/init.c (wait_connectable): fix error handling code.
RB_WAITFD_OUT is turned on even though an error occur.
Wed May 4 10:12:39 2011 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
* ext/readline/readline.c (readline_event): use rb_wait_for_single_fd().

Просмотреть файл

@ -258,22 +258,42 @@ wait_connectable(int fd)
{
int sockerr;
socklen_t sockerrlen;
int r;
int revents;
int ret;
for (;;) {
r = rb_wait_for_single_fd(fd, RB_WAITFD_OUT|RB_WAITFD_PRI, NULL);
if ((r > 0) && (r & RB_WAITFD_OUT))
return 0;
/*
* Stevens book says, succuessful finish turn on RB_WAITFD_OUT and
* failure finish turn on both RB_WAITFD_IN and RB_WAITFD_OUT.
*/
revents = rb_wait_for_single_fd(fd, RB_WAITFD_IN|RB_WAITFD_OUT, NULL);
sockerrlen = (socklen_t)sizeof(sockerr);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr,
&sockerrlen) == 0) {
if (revents & (RB_WAITFD_IN|RB_WAITFD_OUT)) {
sockerrlen = (socklen_t)sizeof(sockerr);
ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
/*
* Solaris getsockopt(SO_ERROR) return -1 and set errno
* in getsockopt(). Let's return immediately.
*/
if (ret < 0)
break;
if (sockerr == 0)
continue; /* workaround for winsock */
/* BSD and Linux use sockerr. */
errno = sockerr;
ret = -1;
break;
}
if ((revents & (RB_WAITFD_IN|RB_WAITFD_OUT)) == RB_WAITFD_OUT) {
ret = 0;
break;
}
return -1;
}
return ret;
}
#ifdef __CYGWIN__