On Wed, 1 Nov 2006, Francis Cianfrocca wrote:

> Ara, I'm curious to know why you think the usage of nbio is archaic or
> indicative of a design flaw. I wrote the EventMachine library in order to
> make certain kinds of Ruby programs easier to write, and it uses nbio
> pervasively. I'm fairly sure libevent does, also. EM works with almost any
> kind of descriptor, except for certain things on Windows (like _pipe()
> descriptors, which are nonselectable, and some of the native Windows objects
> that don't support a socket-like API).
>
> Up until recently (late May 2006), Ruby didn't have complete support for
> nbio on all descriptor types, which is one of the reasons that EventMachine
> includes a compiled C++ extension. EM interoperates perfectly well with Ruby
> threads,* which is another important reason to use nbio.

hi francis-

it's exactly things like eventmachine that make me say using nbio is archaic -
i don't need to handle the complexities of nbio when powerful abstractions
like it exist!

for instance, consider the OP's orignial question: basically he wanted to
timeout if stdout was not produced in a certain amount of time.  i certainly
wouldn't delve into the complexities of nbio to handle this, but instaed might
do something along the lines of

   harrp:~ > cat a.rb
   require 'open4' and require 'timeout'

   def might_take_too_long cmd, stdin, timeout = 42
     stdout, stderr = '', ''
     Timeout::timeout(timeout) do
       open4.popen4(cmd) do |cid,i,o,e|
         i.write stdin and i.close
         o.each{|line| stdout << line} and e.each{|line| stderr << line}
       end
     end
     [ stdout, stderr ]
   end

   p  might_take_too_long('ruby', 'sleep 1 and p 42', 2)
   p  might_take_too_long('ruby', 'sleep 42 and p 42', 2)


   harp:~ > ruby a.rb
   ["42\n", ""]
   /home/ahoward//lib/ruby/1.8/timeout.rb:43:in `might_take_too_long': execution expired (Timeout::Error)
   <snip>


now, timeout might use any manner of select and/or nbio - i don't care.  my
point is just that, for 90-99% of the problems seem to want to solve with
nbio, it is way too low level a mechanism to skin the cat and prefer to stand
on the shoulders of powerful abstractions, like eventmachine or threads or
whatever, and avoid the painful details of EAGAIN, race conditions (it wasn't
ready so i... oops, now it is ready), and stdio buffers being lost.

for the record, i have code which uses nbio, io/nonblock, etc.  it's simply my
observation that a majority of the posts to this list about nbio have two
issues:

   - nothing else can really be done while waiting for io.  eg.  nbio isn't
     needed for the problem at hand

   - something else could simoultaneously be done, but the problem could be
     more elegantly solved with threads, queues, readpartial, or something even
     more abstract

the rest, of course, really do need nbio.  a quick search of archives though
is an eye opener into the difficulties of mixing nbio and stdio, check out
these threads, specifically the posts by tanaka akira, who knows about 10
billion times more about nbio and ruby than i do

   http://groups-beta.google.com/group/comp.lang.ruby/browse_frm/thread/47b0e296cbe9c410/23e22cc9e56a3200?lnk=gst&q=non+blocking+io&rnum=1#23e22cc9e56a3200

   http://groups-beta.google.com/group/comp.lang.ruby/browse_frm/thread/116231c43621a61b/775af5d9900aa716?lnk=gst&q=non+blocking+io&rnum=6#775af5d9900aa716

   http://groups-beta.google.com/group/comp.lang.ruby/browse_frm/thread/116231c43621a61b/775af5d9900aa716?lnk=gst&q=non+blocking+io&rnum=6#775af5d9900aa716

   http://groups-beta.google.com/group/comp.lang.ruby/browse_frm/thread/116231c43621a61b/775af5d9900aa716?lnk=gst&q=non+blocking+io&rnum=6#775af5d9900aa716


his insight is enough to raise 'too low-level' warnings in my mind!  at least
until using nbio from a ruby script doesn't require such deep understanding of
ruby's internals

kind regards.

-a
-- 
my religion is very simple.  my religion is kindness. -- the dalai lama