Hi,

From: "U.Nakamura" <usa / osb.att.ne.jp>
>
> Hello,
>
> In message "Re: bug: threads and win32"
>     on Dec.26,2003 10:17:32, <surrender_it / rc1.vip.ukl.yahoo.com> wrote:
> | >Try this patch to win32/win32.c ( ruby 1.8.0 )
> | >I adoted this from php 5.0.0 beta 3 source code.
> | >I believe it will fix thread and blocking IO problem whinin Windows.
> |
> | have you tried it? If it works, why don't you submit it to ruby-core ?
> | This would be really cool  :)
>
> Of course, we (ruby windows version maintainers) are testing
> this patch. and already found some problems.
> (for example, `ruby test/runner.rb' doesn't run...)
>
> Now we are trying to fix the problems to import this patch to
> ruby 1.9 (and 1.8.2, if we can...).
>
>
Here is the patch for ruby 1.8.1.
At least, it works with test/runner.rb.

=================================================================
--- win32.c Fri Dec 26 12:47:35 2003
+++ win32.c Fri Dec 26 12:46:44 2003
@@ -1819,6 +1819,13 @@
 rb_w32_select (int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
         struct timeval *timeout)
 {
+    DWORD ms_total, limit;
+    HANDLE handles[MAXIMUM_WAIT_OBJECTS];
+    int handle_slot_to_fd[MAXIMUM_WAIT_OBJECTS];
+    int n_handles = 0, i;
+    fd_set aread, awrite, aexcept;
+    int retcode;
+
     long r;
     fd_set file_rd;
     fd_set file_wr;
@@ -1827,6 +1834,26 @@
 #endif /* USE_INTERRUPT_WINSOCK */
     int file_nfds;

+#define SAFE_FD_ISSET(fd, set) (set != NULL && rb_w32_fdisset(fd, set))
+ /* calculate how long we need to wait in milliseconds */
+ if (timeout == NULL) {
+  ms_total = INFINITE;
+ } else {
+  ms_total = timeout->tv_sec * 1000;
+  ms_total += timeout->tv_usec / 1000;
+ }
+
+ /* build an array of handles for non-sockets */
+ for (i = 0; i <= nfds; i++) {
+  if (SAFE_FD_ISSET(i, rd) || SAFE_FD_ISSET(i, wr)) {
+   handles[n_handles] = (HANDLE)TO_SOCKET(i);
+   if ((DWORD)handles[n_handles] != 0xffffffff &&
!is_socket((SOCKET)handles[n_handles]) && (SOCKET)handles[n_handles]<20) {
/* 20 is trial & error */
+    handle_slot_to_fd[n_handles] = i;
+    n_handles++;
+   }
+  }
+ }
+
     if (!NtSocketsInitialized) {
  StartSockets();
     }
@@ -1843,10 +1870,56 @@
     file_nfds += extract_file_fd(wr, &file_wr);
     if (file_nfds)
     {
+        if(n_handles>0) {
+   FD_ZERO(&aread);
+   FD_ZERO(&awrite);
+
+          limit = GetTickCount() + ms_total;
+
+          do {
+     DWORD wret;
+            retcode = 0;
+
+     wret = MsgWaitForMultipleObjects(n_handles, handles, FALSE, retcode >
0 ? 0 : 100, QS_ALLEVENTS);
+
+     if (wret == WAIT_TIMEOUT) {
+   /* set retcode to 0; this is the default.
+    * select() may have set it to something else,
+    * in which case we leave it alone, so this branch
+    * does nothing */
+   ;
+        } else if (wret == WAIT_FAILED) {
+  if (retcode == 0) {
+   retcode = -1;
+  }
+      } else {
+  if (retcode < 0) {
+   retcode = 0;
+  }
+         for (i = 0; i < n_handles; i++) {
+      if (WAIT_OBJECT_0 == WaitForSingleObject(handles[i], 0)) {
+
+   if (SAFE_FD_ISSET(handle_slot_to_fd[i], rd)) {
+    rb_w32_fdset(handle_slot_to_fd[i], &aread);
+   }
+   if (SAFE_FD_ISSET(handle_slot_to_fd[i], wr)) {
+    rb_w32_fdset(handle_slot_to_fd[i], &awrite);
+   }
+
+   retcode++;
+      }
+  }
+            }
+          } while (retcode == 0 && (ms_total == INFINITE || GetTickCount()
< limit));
+   if (rd) *rd = aread;
+   if (wr) *wr = awrite;
+        }
+        else {
  // assume normal files are always readable/writable
  // fake read/write fd_set and return value
  if (rd) *rd = file_rd;
  if (wr) *wr = file_wr;
+        }
  return file_nfds;
     }

===================================================================

Regards,

Park Heesob