Hi,

Luis Lavena wrote:
> On Mar 27, 2:41 am, "Just Another Victim of the .. Morality"
> <ihates... / hotmail.com> wrote:
>> necessarily so or can we change this?  Shouldn't we like to change this?
>>         count += 1
>>     end
>> end
>> gets
> 
> I've asked about this back in September 2007 at ruby-core mailing
> list, no answer. I'm copying my post with details more information:
> 
> Hello Ruby Developers.
> 
> I've been trying to determine what is wrong with this simple script:
> 
> http://pastie.caboo.se/101434
> 
> t = Thread.new {
>    while true
>      puts "printing a line"
>      sleep 2
>    end
>  }
> 
> gets
> t.exit
> puts "exiting"
> 
> ===
> 
> And found that all the IO (stdin) is broken on Windows:
> custom build with MinGW (3.4.5 -- mingw special)
> custom build with VC8
> official build VC6
> 
> All behave the same way: just 1 line of "printing a line" gets
> actually printed, and the world halt until you hit enter.
> 
> I saw a few post dating 2003 about this... and this brakes the
> cross-platform nature of most of ruby: works on some platform, don't
> work on other.
> 
> Since 1.8.6 will stay with us a bit longer, any ideas how to solve it?
> 
> Park Heesob posted a patch back then, but it don't work as expected
> (this problem didn't get solved).
> 
> For the record: 1.9.0 don't show this issue, but YARV is another
> different breed.
> 
> Thanks in advance for your time.
> 
> ==
> 
> Even it doesn't solve your issue, explain it better.
> 
> Still, no answer, no solution :'(
> 
> Regards,

Here is the patched code of rb_win_selected function
(win32.c,ruby-1.8.6-p111)
It will fix Thread blocking problem with standard input waiting.

long
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;
#ifdef USE_INTERRUPT_WINSOCK
    fd_set trap;
#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 ((SOCKET)handles[n_handles]==TO_SOCKET(0)) { /* only treat stdin
*/
    handle_slot_to_fd[n_handles] = i;
    n_handles++;
   }
  }
 }

    if (!NtSocketsInitialized) {
  StartSockets();
    }
    r = 0;
    if (rd && rd->fd_count > r) r = rd->fd_count;
    if (wr && wr->fd_count > r) r = wr->fd_count;
    if (ex && ex->fd_count > r) r = ex->fd_count;
    if (nfds > r) nfds = r;
    if (nfds == 0 && timeout) {
  Sleep(timeout->tv_sec * 1000 + timeout->tv_usec / 1000);
  return 0;
    }
    file_nfds = extract_file_fd(rd, &file_rd);
    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;
    }

#if USE_INTERRUPT_WINSOCK
    if (ex)
  trap = *ex;
    else
  trap.fd_count = 0;
    if (trap.fd_count < FD_SETSIZE)
  trap.fd_array[trap.fd_count++] = (SOCKET)interrupted_event;
    // else unable to catch interrupt.
    ex = &trap;
#endif /* USE_INTERRUPT_WINSOCK */

    RUBY_CRITICAL({
  r = select(nfds, rd, wr, ex, timeout);
  if (r == SOCKET_ERROR) {
      errno = map_errno(WSAGetLastError());
  }
    });
    return r;
}


Regards,
Park Heesob
-- 
Posted via http://www.ruby-forum.com/.