diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-08-20 07:44:53 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-08-20 07:44:53 +0000 |
commit | b1f01153943b95019ecc56192527e9fb00adb240 (patch) | |
tree | 8a7234514cf4de4359851e28c0baa4456f390cfb /ext | |
parent | 360b0a015aba72f62ea2ffee4f52ce2b9132a2d1 (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')
-rw-r--r-- | ext/socket/socket.c | 28 |
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}; |