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...gst&q=non+blocking+io&rnum=1#23e22cc9e56a3200
http://groups-beta.google.com/group...gst&q=non+blocking+io&rnum=6#775af5d9900aa716
http://groups-beta.google.com/group...gst&q=non+blocking+io&rnum=6#775af5d9900aa716
http://groups-beta.google.com/group...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