[#3228] Core support for Gems, and namespace — "Luke A. Kanies" <luke@...>

Hi all,

21 messages 2004/07/27
[#3230] Re: Core support for Gems, and namespace — Austin Ziegler <halostatue@...> 2004/07/27

On Tue, 27 Jul 2004 11:39:08 +0900, Luke A. Kanies <luke@madstop.com> wrote:

[#3234] Re: Core support for Gems, and namespace — "Luke A. Kanies" <luke@...> 2004/07/27

On Tue, 27 Jul 2004, Austin Ziegler wrote:

[#3238] Re: Core support for Gems, and namespace — Austin Ziegler <halostatue@...> 2004/07/27

On Wed, 28 Jul 2004 00:14:29 +0900, Luke A. Kanies <luke@madstop.com> wrote:

Re: UPDATE - [PATCH] Nonblocking socket connect - Win32 - 181

From: "Jean-Francois Nadeau" <jean-francois.nadeau@...>
Date: 2004-07-08 02:33:13 UTC
List: ruby-core #3155
Hi,

I missed something with the last patch. I don't know why, but Windows
signals the fd in "except" a lot of times, even though the connect process
hasn't failed yet.

Well, here the last patch that fixes this problem. Now, everything seems to
work.

I now call rb_thread_select in a loop and when the "except" fd is set, I
check for a socket error using getsockopt. If I get no error, I loop back on
rb_thread_select. At the end of the process, I finally get an error code
from getsockopt and then, I return the error to ruby.

If you have an explanation for this behavior, please tell me, I am very
interested to know the answer.

Regards,

Jean-Francois Nadeau
http://www.jfnadeau.com

Attachments (1)

nonblocking_connect_w32_181.patch.txt (3.96 KB, text/x-diff)
Index: ext/socket/socket.c
===================================================================
RCS file: /src/ruby/ext/socket/socket.c,v
retrieving revision 1.108
diff -u -r1.108 socket.c
--- ext/socket/socket.c	14 Dec 2003 10:04:34 -0000	1.108
+++ ext/socket/socket.c	8 Jul 2004 02:22:22 -0000
@@ -738,6 +738,48 @@
     rb_thread_select(fd+1, 0, &fds, 0, 0);
 }
 
+#ifdef _WIN32
+
+static int
+thread_w32_connect_select(fd)
+    int fd;
+{
+
+    int sockerr, sockerrlen, r;
+    fd_set fds_w;
+    fd_set fds_e;
+
+    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, 0);
+
+    	if (FD_ISSET(fd, &fds_w)) {
+		return 0;
+		
+    	} else if (FD_ISSET(fd, &fds_e)) {
+
+		sockerrlen = sizeof(sockerr);
+		r = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen);
+
+		if (r != 0) {
+			return WSAGetLastError();
+		} else if(sockerr != 0) {
+			return sockerr;
+		}
+	}
+    }
+
+    return 0;
+}
+
+#endif
+
 #ifdef __CYGWIN__
 #define WAIT_IN_PROGRESS 10
 #endif
@@ -767,6 +809,11 @@
     int sockerr, sockerrlen;
 #endif
 
+#ifdef _WIN32
+	u_long ioctlArg;
+	int connecterr;
+#endif
+
 #if defined(HAVE_FCNTL)
     mode = fcntl(fd, F_GETFL, 0);
 
@@ -785,6 +832,11 @@
     fcntl(fd, F_SETFL, mode|NONBLOCKING);
 #endif /* HAVE_FCNTL */
 
+#ifdef _WIN32
+	ioctlArg = 1;
+	ioctlsocket(fd, FIONBIO, &ioctlArg);
+#endif
+
     for (;;) {
 #if defined(SOCKS) && !defined(SOCKS5)
 	if (socks) {
@@ -817,7 +869,21 @@
 #if WAIT_IN_PROGRESS > 0
 		wait_in_progress = WAIT_IN_PROGRESS;
 #endif
+#ifndef _WIN32
 		thread_write_select(fd);
+#endif
+#ifdef _WIN32
+		connecterr = thread_w32_connect_select(fd);
+		if (connecterr) {
+		    status = -1;
+		    errno = connecterr;
+		    break;
+		}
+
+		status = 0;
+		errno = 0;
+		break;
+#endif
 		continue;
 
 #if WAIT_IN_PROGRESS > 0
@@ -854,6 +920,12 @@
 #ifdef HAVE_FCNTL
 	fcntl(fd, F_SETFL, mode);
 #endif
+
+#ifdef _WIN32
+	ioctlArg = 0;
+	ioctlsocket(fd, FIONBIO, &ioctlArg);
+#endif
+
 	return status;
     }
 }
@@ -2362,6 +2434,43 @@
     rb_define_const(mConst, name, INT2FIX(value));
 }
 
+#ifdef _WIN32
+
+static VALUE
+rb_w32_socket_fcntl(self, vcmd, varg)
+    VALUE vcmd;
+    VALUE varg;
+{
+	int cmd, arg;
+	OpenFile *fptr;
+	u_long ioctlArg;
+
+	cmd = NUM2INT(vcmd);
+	arg = NUM2INT(varg);
+
+	if (cmd == F_SETFL) {
+
+		if (arg & O_NONBLOCK) {
+			ioctlArg = 1;
+		} else {
+			ioctlArg = 0;
+		}
+
+		GetOpenFile(self, fptr);
+		if(ioctlsocket(fileno(fptr->f), FIONBIO, &ioctlArg) < 0)
+				rb_sys_fail("ioctlsocket");
+
+		return Qnil;
+
+	} else {
+
+		rb_notimplement();
+		return Qnil;
+	}
+}
+
+#endif
+
 void
 Init_socket()
 {
@@ -2405,6 +2514,10 @@
 #ifdef SOCKS5
     rb_define_method(rb_cSOCKSSocket, "close", socks_s_close, 0);
 #endif
+#endif
+
+#ifdef _WIN32
+	rb_define_method(rb_cIO, "fcntl", rb_w32_socket_fcntl, 2);
 #endif
 
     rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket);
Index: win32/win32.c
===================================================================
RCS file: /src/ruby/win32/win32.c,v
retrieving revision 1.103
diff -u -r1.103 win32.c
--- win32/win32.c	27 Nov 2003 09:13:50 -0000	1.103
+++ win32/win32.c	7 Jul 2004 22:23:42 -0000
@@ -1969,8 +1969,15 @@
     }
     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;
 }
Index: win32/win32.h
===================================================================
RCS file: /src/ruby/win32/win32.h,v
retrieving revision 1.46
diff -u -r1.46 win32.h
--- win32/win32.h	22 Dec 2003 08:23:55 -0000	1.46
+++ win32/win32.h	7 Jul 2004 21:06:52 -0000
@@ -312,6 +312,9 @@
 #define ESTALE		WSAESTALE
 #define EREMOTE		WSAEREMOTE
 
+#define F_SETFL 1
+#define O_NONBLOCK 1
+
 #ifdef accept
 #undef accept
 #endif

In This Thread