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