Win32OperatingSystem.st
branchjv
changeset 21628 b0dcdf5fe53d
parent 21387 e3865533e6a6
child 21638 dc75b3c9c537
--- a/Win32OperatingSystem.st	Tue Feb 28 09:32:24 2017 +0000
+++ b/Win32OperatingSystem.st	Sun Mar 05 21:13:56 2017 +0000
@@ -12033,7 +12033,10 @@
 //#define SELECTDEBUGWIN32
 //#define SELECT3DEBUGWIN32
 #define MAXHANDLE 128
-    int i;
+    int i, idx;
+    INT t;
+    int numHandles;
+    DWORD res;
     HANDLE hArray[MAXHANDLE+1];
     int retArray[MAXHANDLE];
     int readCount, writeCount, exceptCount;
@@ -12043,7 +12046,8 @@
     fd_set readFds;
     fd_set writeFds;
     fd_set exceptFds;
-    int numHandles, numSockets, numPipes;
+    int hasSockets;
+    int hasPipes;
     int pass = 1;       // perform up to 2 passes
 
     if (readableResultFdArray != nil) {
@@ -12100,7 +12104,7 @@
     FD_ZERO(&readFds);
     FD_ZERO(&writeFds);
     FD_ZERO(&exceptFds);
-    numHandles = numSockets = numPipes = 0;
+    numHandles = hasSockets = hasPipes = 0;
 
     for (i = 0; (i < readCount) && (numHandles < MAXHANDLE); i++) {
 	OBJ fd = __arrayVal(readFdArray)[i];
@@ -12108,7 +12112,7 @@
 	if (fd != nil) {
 	    if (__Class(fd) == @global(Win32SocketHandle)) {
 		FD_SET (_HANDLEVal(fd), &readFds);
-		numSockets++;
+		hasSockets++;
 	    } else if (__isSmallInteger(fd)) {
 		DWORD canRead;
 		if (PeekNamedPipe(_get_osfhandle(__intVal(fd)), 0, 0, 0, &canRead, 0)) {
@@ -12122,7 +12126,7 @@
 		    @global(LastErrorNumber) = __mkSmallInteger(EBADF);
 		    RETURN (__mkSmallInteger(-1));
 		}
-		numPipes++;
+		hasPipes++;
 	    } else {
 		hArray  [numHandles] = _HANDLEVal(fd);
 		retArray[numHandles] = i;
@@ -12137,7 +12141,7 @@
 	if (fd != nil) {
 	    if (__Class(fd) == @global(Win32SocketHandle)) {
 		FD_SET (_HANDLEVal(fd), &writeFds);
-		numSockets++;
+		hasSockets++;
 	    } else if (__isSmallInteger(fd)) {
 		// kludge: assume that pipes can alway be written
 	       if (*pcntW < resultSizeWritable) {
@@ -12159,7 +12163,7 @@
 	if (fdOrPid != nil) {
 	    if (__Class(fdOrPid) == @global(Win32SocketHandle)) {
 		FD_SET (_HANDLEVal(fdOrPid), &exceptFds);
-		numSockets++;
+		hasSockets++;
 	    } else if (__isExternalAddressLike(fdOrPid)) {
 		// a PID
 		hArray  [numHandles] = _HANDLEVal(fdOrPid);
@@ -12169,37 +12173,96 @@
 	}
     }
 
-    // +++++ checking for Windows Handles +++++++++++++++++++++++++++++++++++++++++
-    if (numHandles != 0) {
-	DWORD res;
-	int idx;
-	INT t;
-
-	if (numSockets || pass > 1) {
-	    // do not wait - wait when checking for sockets
+    if (hasSockets) {
+	struct timeval tv = {0, 0};
+	int nReady;
+
+#ifdef SELECT3DEBUGWIN32
+	console_printf("select hasSockets = %d\n", hasSockets);
+#endif
+	nReady = select(1 , &readFds, &writeFds, &exceptFds, &tv);  // first parameter to select is ignored in windows
+	if (nReady < 0) {
+#ifdef SELECTDEBUGWIN32
+	    console_printf("error in select %d %d\n", nReady, GetLastError());
+#endif
+	    @global(LastErrorNumber) = __mkSmallInteger(EBADF);
+	    RETURN (__mkSmallInteger(-1));
+	}
+	if (nReady > 0) {
+#ifdef SELECT3DEBUGWIN32
+	    console_printf("select nReady %d of %d\n", nReady, hasSockets);
+#endif
+	    for (i = 0; i < readCount; i++) {
+		OBJ fd = __arrayVal(readFdArray)[i];
+		if ((__Class(fd) == @global(Win32SocketHandle)) && FD_ISSET(_HANDLEVal(fd), &readFds)) {
+		    if (*pcntR < resultSizeReadable) {
+			__arrayVal(readableResultFdArray)[*pcntR] = fd;
+			__STORE(readableResultFdArray, fd);
+		    }
+		    (*pcntR)++; cntAll++;
+		}
+	    }
+	    for (i = 0; i < writeCount; i++) {
+		OBJ fd = __arrayVal(writeFdArray)[i];
+		if ((__Class(fd) == @global(Win32SocketHandle)) && FD_ISSET(_HANDLEVal(fd), &writeFds)) {
+		    if (*pcntW < resultSizeWritable) {
+			__arrayVal(writableResultFdArray)[*pcntW] = fd;
+			__STORE(writableResultFdArray, fd);
+		    }
+		    (*pcntW)++; cntAll++;
+		}
+	    }
+	    for (i = 0; i < exceptCount; i++) {
+		OBJ fd = __arrayVal(exceptFdArray)[i];
+		if ((__Class(fd) == @global(Win32SocketHandle)) && FD_ISSET(_HANDLEVal(fd), &exceptFds)) {
+		    if (*pcntE < resultSizeException) {
+			__arrayVal(exceptionResultFdArray)[*pcntE] = fd;
+			__STORE(exceptionResultFdArray, fd);
+		    }
+		    (*pcntE)++; cntAll++;
+		}
+	    }
+
+	}
+    }
+    if (pass > 1)       // perform maximum 2 passes
+	goto done;
+
+    if (cntAll) {
+	// check for other handles and return immediately, no timeout
 	    t = 0;
-	} else if (__isSmallInteger(millis)) {
+    } else {
+	if (__isSmallInteger(millis)) {
 	    t = __intVal(millis);
+
+	    if (t <= 0 && numHandles == 0) {
+		RETURN (__mkSmallInteger(0));
+	    }
 	} else {
 	    t = INFINITE;
 	}
+    }
+
+    if (numHandles == 0 && t == 0) {
+	// nothing to do and no wait
+	goto done;
+    }
 
 #ifdef SELECT3DEBUGWIN32
 	console_printf("wait numhandles = %d timeout = %d\n", numHandles, t);
 #endif
 
-	res = __vmWait(numHandles, hArray, MAXHANDLE, (int)t);
+    res = __vmWait(numHandles, hArray, MAXHANDLE, t);
 
 	if (res == WAIT_TIMEOUT) {
 #ifdef SELECT3DEBUGWIN32
-	    console_printf("- timeOut" );
-#endif
-	    goto checkSockets;
-	}
-	if (res == __WAIT_INTERRUPTED) {
-#ifdef SELECT3DEBUGWIN32
-	    console_printf("- interrupted\n" );
-#endif
+	console_printf("- timeOut; ret nil\n" );
+#endif
+	if (t != 0 && (hasSockets || hasPipes)) {
+	    // if not a single handle is ready, poll sockets an pipes again
+	    pass = 2;
+	    goto pollAgain;
+	}
 	    goto done;
 	}
 
@@ -12220,15 +12283,16 @@
 	    }
 	}
 
-	if ((res < 0) || (res >= numHandles)) {
+    if (numHandles) {
 	    if (res == numHandles) {
 		// vmwait() added an IRQ event to the handles, and this one has been triggered
 		if (1 /* @global(InfoPrinting) == true */) {
 		    console_fprintf(stderr, "Win32OS [info]: plugIn event has been handled\n");
 		}
-	    } else {
-		console_printf("- res=%d error1 %d\n", res, GetLastError());
-	    }
+	    goto done;
+	    }
+	if ((res < 0) || (res >= numHandles)) {
+	    console_printf("- res=%d error1 %d\n", res, GetLastError());
 	    goto done;
 	}
 
@@ -12274,81 +12338,11 @@
 #endif
 	}
     }
-
-
-// ++++++++++ Check Sockets +++++++++++++++++++++++++++++++++++
-checkSockets:
-    if (pass > 1)       // perform maximum 2 passes
-	goto done;
-
-    if (numSockets) {
-	struct timeval tv = {0, 0};
-	struct timeval *tvp = &tv;
-	int nReady;
-
-	// do not wait, if there are threads that can be resumed
-	if (!__vmTestIfAnyThreadMustBeResumed() && cntAll == 0) {
-	    // no ready handles found yet - do wait
-	    if (__isSmallInteger(millis)) {
-		tv.tv_usec = __intVal(millis) * 1000;
-	    } else {
-		// no timeout
-		tvp = 0;
-	    }
-	}
-
-#ifdef SELECT3DEBUGWIN32
-	console_printf("select numSockets = %d\n", numSockets);
-#endif
-	nReady = select(1 , &readFds, &writeFds, &exceptFds, tvp);  // first parameter to select is ignored in windows
-	if (nReady < 0) {
-#ifdef SELECTDEBUGWIN32
-	    console_printf("error in select %d %d\n", nReady, GetLastError());
-#endif
-	    @global(LastErrorNumber) = __mkSmallInteger(EBADF);
-	    RETURN (__mkSmallInteger(-1));
-	}
-	if (nReady > 0) {
-#ifdef SELECT3DEBUGWIN32
-	    console_printf("select nReady %d of %d\n", nReady, numSockets);
-#endif
-	    for (i = 0; i < readCount; i++) {
-		OBJ fd = __arrayVal(readFdArray)[i];
-		if ((__Class(fd) == @global(Win32SocketHandle)) && FD_ISSET(_HANDLEVal(fd), &readFds)) {
-		    if (*pcntR < resultSizeReadable) {
-			__arrayVal(readableResultFdArray)[*pcntR] = fd;
-			__STORE(readableResultFdArray, fd);
-		    }
-		    (*pcntR)++; cntAll++;
-		}
-	    }
-	    for (i = 0; i < writeCount; i++) {
-		OBJ fd = __arrayVal(writeFdArray)[i];
-		if ((__Class(fd) == @global(Win32SocketHandle)) && FD_ISSET(_HANDLEVal(fd), &writeFds)) {
-		    if (*pcntW < resultSizeWritable) {
-			__arrayVal(writableResultFdArray)[*pcntW] = fd;
-			__STORE(writableResultFdArray, fd);
-		    }
-		    (*pcntW)++; cntAll++;
-		}
-	    }
-	    for (i = 0; i < exceptCount; i++) {
-		OBJ fd = __arrayVal(exceptFdArray)[i];
-		if ((__Class(fd) == @global(Win32SocketHandle)) && FD_ISSET(_HANDLEVal(fd), &exceptFds)) {
-		    if (*pcntE < resultSizeException) {
-			__arrayVal(exceptionResultFdArray)[*pcntE] = fd;
-			__STORE(exceptionResultFdArray, fd);
-		    }
-		    (*pcntE)++; cntAll++;
-		}
-	    }
-	}
-	if (tvp && tv.tv_usec != 0 && (numHandles != 0 || numPipes != 0)) {
-	    // back after timeout, maybe some handles or pipes did wake up
+    if (t != 0 && (hasSockets || hasPipes)) {
+	// back after timeout, maybe some sockets or pipes did wake up
 	    // in the meantime?
 	    pass = 2;
 	    goto pollAgain;
-	}
     }
 
 done:
@@ -12374,8 +12368,6 @@
      or not supported by OS
     "
     ^ self primitiveFailed
-
-    "Modified: / 15-01-2017 / 03:04:41 / stefan"
 !
 
 setBlocking:aBoolean on:fd