diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | bcc32/Makefile.sub | 1 | ||||
-rw-r--r-- | ext/socket/socket.c | 52 | ||||
-rw-r--r-- | win32/Makefile.sub | 1 | ||||
-rw-r--r-- | win32/win32.c | 49 | ||||
-rw-r--r-- | win32/win32.h | 4 | ||||
-rw-r--r-- | wince/Makefile.sub | 1 |
7 files changed, 112 insertions, 9 deletions
@@ -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 |