summaryrefslogtreecommitdiff
path: root/ext/socket/init.c
diff options
context:
space:
mode:
authorkosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-05-04 02:44:28 +0000
committerkosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-05-04 02:44:28 +0000
commit9851b0ce2fbc5934ddd00434048be4273f41102d (patch)
treebdd27a175928e98de6e1dca086a5d052b52e56d3 /ext/socket/init.c
parent4da4cb0421fbdd5c7a825addcda9c8725e86c844 (diff)
* 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
Diffstat (limited to 'ext/socket/init.c')
-rw-r--r--ext/socket/init.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/ext/socket/init.c b/ext/socket/init.c
index 4c32ab4720..e55736cabe 100644
--- a/ext/socket/init.c
+++ b/ext/socket/init.c
@@ -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;
-
- sockerrlen = (socklen_t)sizeof(sockerr);
- if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr,
- &sockerrlen) == 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);
+
+ 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__