summaryrefslogtreecommitdiff
path: root/ext/socket/socket.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-08-20 07:44:53 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-08-20 07:44:53 +0000
commitb1f01153943b95019ecc56192527e9fb00adb240 (patch)
tree8a7234514cf4de4359851e28c0baa4456f390cfb /ext/socket/socket.c
parent360b0a015aba72f62ea2ffee4f52ce2b9132a2d1 (diff)
* ext/socket/socket.c (ruby_connect): many systems seem to have
a problem in select() after EINPROGRESS. [ruby-list:38080] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4415 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/socket/socket.c')
-rw-r--r--ext/socket/socket.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index 13329eedcb..2130d5f53c 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -731,6 +731,14 @@ thread_write_select(fd)
#ifdef __APPLE__
#define WAIT_IN_PROGRESS 10
#endif
+#ifdef __linux__
+/* returns correct error */
+#define WAIT_IN_PROGRESS 0
+#endif
+#ifndef WAIT_IN_PROGRESS
+/* BSD origin code apparently has a problem */
+#define WAIT_IN_PROGRESS 1
+#endif
static int
ruby_connect(fd, sockaddr, len, socks)
@@ -741,8 +749,9 @@ ruby_connect(fd, sockaddr, len, socks)
{
int status;
int mode;
-#ifdef WAIT_IN_PROGRESS
+#if WAIT_IN_PROGRESS > 0
int wait_in_progress = -1;
+ int sockerr, sockerrlen;
#endif
#if defined(HAVE_FCNTL)
@@ -779,25 +788,34 @@ ruby_connect(fd, sockaddr, len, socks)
#ifdef EINPROGRESS
case EINPROGRESS:
#endif
+#if WAIT_IN_PROGRESS > 0
+ sockerrlen = sizeof(sockerr);
+ status = getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &sockerrlen);
+ if (status) break;
+ if (sockerr) {
+ status = -1;
+ errno = sockerr;
+ break;
+ }
+#endif
#ifdef EALREADY
case EALREADY:
#endif
-#ifdef WAIT_IN_PROGRESS
+#if WAIT_IN_PROGRESS > 0
wait_in_progress = WAIT_IN_PROGRESS;
#endif
thread_write_select(fd);
continue;
-#ifdef WAIT_IN_PROGRESS
+#if WAIT_IN_PROGRESS > 0
case EINVAL:
if (wait_in_progress-- > 0) {
- int sockerr, sockerrlen = sizeof(sockerr);
-
/*
* connect() after EINPROGRESS returns EINVAL on
* some platforms, need to check true error
* status.
*/
+ sockerrlen = sizeof(sockerr);
status = getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &sockerrlen);
if (!status && !sockerr) {
struct timeval tv = {0, 100000};