summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-02-21 01:08:56 +0000
committerusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-02-21 01:08:56 +0000
commit5fec8532294c2bf7a72258c90ad62dbee5585ac8 (patch)
treeb32c78ba0a408f9026019f15a2ce899de96d39f1
parent6804916270b55f1a33dae72062fabfb3727adb7d (diff)
* {bcc32,win32,wince}/Makefile.sub (config.h): add fcntl.
* win32/win32.[ch] (fcntl): ditto. * win32/win32.c (rb_w32_connect): support nonblocking mode. * ext/socket/socket.c (wait_connectable, ruby_connect): support nonblocking connect on various platforms. all changes are backported from CVS HEAD. [ruby-core:3154], [ruby-core:4364]. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@8005 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog13
-rw-r--r--bcc32/Makefile.sub1
-rw-r--r--ext/socket/socket.c52
-rw-r--r--win32/Makefile.sub1
-rw-r--r--win32/win32.c49
-rw-r--r--win32/win32.h4
-rw-r--r--wince/Makefile.sub1
7 files changed, 112 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 40b0d37630..b44a55ef9e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+Mon Feb 21 10:04:49 2005 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * {bcc32,win32,wince}/Makefile.sub (config.h): add fcntl.
+
+ * win32/win32.[ch] (fcntl): ditto.
+
+ * win32/win32.c (rb_w32_connect): support nonblocking mode.
+
+ * ext/socket/socket.c (wait_connectable, ruby_connect): support
+ nonblocking connect on various platforms.
+ all changes are backported from CVS HEAD. [ruby-core:3154],
+ [ruby-core:4364].
+
Sun Feb 20 00:48:48 2005 Tanaka Akira <akr@m17n.org>
* lib/open-uri.rb (URI::FTP#buffer_open): access mechanism
diff --git a/bcc32/Makefile.sub b/bcc32/Makefile.sub
index 6d87bd4304..cac6128bdb 100644
--- a/bcc32/Makefile.sub
+++ b/bcc32/Makefile.sub
@@ -259,6 +259,7 @@ config.h:
\#define HAVE_GETCWD 1
\#define HAVE_CHSIZE 1
\#define HAVE_TIMES 1
+\#define HAVE_FCNTL 1
\#define HAVE_LINK 1
\#define HAVE_TELLDIR 1
\#define HAVE_SEEKDIR 1
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index 97df7cf780..ac2a84b2a5 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -52,10 +52,16 @@
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
+#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
+#endif
+#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
+#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
#endif
@@ -755,15 +761,39 @@ ruby_socket(domain, type, proto)
return fd;
}
-static void
-thread_write_select(fd)
+static int
+wait_connectable(fd)
int fd;
{
- fd_set fds;
+ int sockerr, sockerrlen;
+ fd_set fds_w;
+ fd_set fds_e;
- FD_ZERO(&fds);
- FD_SET(fd, &fds);
- rb_thread_select(fd+1, 0, &fds, 0, 0);
+ for (;;) {
+ FD_ZERO(&fds_w);
+ FD_ZERO(&fds_e);
+
+ FD_SET(fd, &fds_w);
+ FD_SET(fd, &fds_e);
+
+ rb_thread_select(fd+1, 0, &fds_w, &fds_e, 0);
+
+ if (FD_ISSET(fd, &fds_w)) {
+ return 0;
+ }
+ else if (FD_ISSET(fd, &fds_e)) {
+ sockerrlen = sizeof(sockerr);
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr,
+ &sockerrlen) == 0) {
+ if (sockerr == 0)
+ continue; /* workaround for winsock */
+ errno = sockerr;
+ }
+ return -1;
+ }
+ }
+
+ return 0;
}
#ifdef __CYGWIN__
@@ -796,7 +826,11 @@ ruby_connect(fd, sockaddr, len, socks)
#endif
#if defined(HAVE_FCNTL)
+# if defined(F_GETFL)
mode = fcntl(fd, F_GETFL, 0);
+# else
+ mode = 0;
+# endif
#ifdef O_NDELAY
# define NONBLOCKING O_NDELAY
@@ -845,7 +879,11 @@ ruby_connect(fd, sockaddr, len, socks)
#if WAIT_IN_PROGRESS > 0
wait_in_progress = WAIT_IN_PROGRESS;
#endif
- thread_write_select(fd);
+ status = wait_connectable(fd);
+ if (status) {
+ break;
+ }
+ errno = 0;
continue;
#if WAIT_IN_PROGRESS > 0
diff --git a/win32/Makefile.sub b/win32/Makefile.sub
index 8dbe5b0edb..af1cc55b38 100644
--- a/win32/Makefile.sub
+++ b/win32/Makefile.sub
@@ -270,6 +270,7 @@ config.h:
#define HAVE_GETCWD 1
#define HAVE_CHSIZE 1
#define HAVE_TIMES 1
+#define HAVE_FCNTL 1
#define HAVE__SETJMP 1
#define HAVE_TELLDIR 1
#define HAVE_SEEKDIR 1
diff --git a/win32/win32.c b/win32/win32.c
index 69080252fb..bc3e2f935e 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -2028,8 +2028,16 @@ rb_w32_connect(int s, struct sockaddr *addr, int addrlen)
}
RUBY_CRITICAL({
r = connect(TO_SOCKET(s), addr, addrlen);
- if (r == SOCKET_ERROR)
- errno = map_errno(WSAGetLastError());
+ if (r == SOCKET_ERROR) {
+ r = WSAGetLastError();
+ if (r != WSAEWOULDBLOCK) {
+ errno = map_errno(r);
+ }
+ else {
+ errno = EINPROGRESS;
+ r = -1;
+ }
+ }
});
return r;
}
@@ -2392,6 +2400,43 @@ void setprotoent (int stayopen) {}
void setservent (int stayopen) {}
+int
+fcntl(int fd, int cmd, ...)
+{
+ SOCKET sock = TO_SOCKET(fd);
+ va_list va;
+ int arg;
+ int ret;
+ u_long ioctlArg;
+
+ if (!is_socket(sock)) {
+ errno = EBADF;
+ return -1;
+ }
+ if (cmd != F_SETFL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ va_start(va, cmd);
+ arg = va_arg(va, int);
+ va_end(va);
+ if (arg & O_NONBLOCK) {
+ ioctlArg = 1;
+ }
+ else {
+ ioctlArg = 0;
+ }
+ RUBY_CRITICAL({
+ ret = ioctlsocket(sock, FIONBIO, &ioctlArg);
+ if (ret == -1) {
+ errno = map_errno(WSAGetLastError());
+ }
+ });
+
+ return ret;
+}
+
#ifndef WNOHANG
#define WNOHANG -1
#endif
diff --git a/win32/win32.h b/win32/win32.h
index a4e5ab20dc..9f0e41fbb8 100644
--- a/win32/win32.h
+++ b/win32/win32.h
@@ -186,6 +186,7 @@ extern pid_t waitpid (pid_t, int *, int);
extern int do_spawn(int, char *);
extern int do_aspawn(int, char *, char **);
extern int kill(int, int);
+extern int fcntl(int, int, ...);
extern pid_t rb_w32_getpid(void);
#if !defined(__BORLANDC__) && !defined(_WIN32_WCE)
@@ -334,6 +335,9 @@ extern char *rb_w32_strerror(int);
#define ESTALE WSAESTALE
#define EREMOTE WSAEREMOTE
+#define F_SETFL 1
+#define O_NONBLOCK 1
+
#ifdef accept
#undef accept
#endif
diff --git a/wince/Makefile.sub b/wince/Makefile.sub
index 7868156206..3d5eed13ae 100644
--- a/wince/Makefile.sub
+++ b/wince/Makefile.sub
@@ -271,6 +271,7 @@ config.h:
#define HAVE_GETCWD 1
#define HAVE_CHSIZE 0
#define HAVE_TIMES 1
+#define HAVE_FCNTL 1
#define HAVE_TELLDIR 1
#define HAVE_SEEKDIR 1
#define HAVE_MKTIME 1