Ok, here’s something that seems wierd. While writing some code to call
Maxima
(http://maxima.sourceforge.net/) from Ruby, I wrote the following:
class IO
Read a line without blocking. If there isn’t a line to be read,
return
nil.
def readline_nonblock
line = ‘’
begin
char = read_nonblock 1 # A larger read would surely be more
efficient.
while char != “\n”
line += char
char = read_nonblock 1
end
rescue Errno::EAGAIN
$stderr.puts ‘*** rescued EAGAIN’
line.reverse.each_byte { |c| ungetc(c) } # Replace partial line.
line = nil
rescue EOFError
line = nil
end
line
end
Yield once for every line recieved from readline_nonblocking, until
it
returns nil.
def each_nonblock
line = readline_nonblock
while not line.nil?
yield line
line = readline_nonblock
end
end
end
The wierdness is that this code behaves differently depending on whether
its
called from IRB’s toplevel or within a method. Here’s some expected
results:
irb(main):001:0> MaximaString = “maxima --batch-string=‘1+1;’”
=> “maxima --batch-string=‘1+1;’”
irb(main):002:0> ios = IO.popen MaximaString
=> #IO:0xb79d6068
irb(main):003:0> ios.each_nonblock { |line| puts line }
i i i i i i i ooooo o ooooooo ooooo ooooo
I I I I I I I 8 8 8 8 8 o 8 8
I \ +' / I 8 8 8 8 8 8 \
-±’ / 8 8 8 ooooo 8oooo
`-|-’ 8 8 8 8 8
| 8 o 8 8 o 8 8
------±----- ooooo 8oooooo ooo8ooo ooooo 8
Copyright (c) Bruno Haible, Michael Stoll 1992, 1993
Copyright (c) Bruno Haible, Marcus Daniels 1994-1997
Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
Copyright (c) Bruno Haible, Sam Steingold 1999-2003
Maxima 5.9.1 http://maxima.sourceforge.net
Using Lisp CLISP 2.38 (2006-01-24)
Distributed under the GNU Public License. See the file COPYING.
Dedicated to the memory of William Schelter.
This is a development version of Maxima. The function bug_report()
provides bug reporting information.
(%i1) 1 + 1
(%o1) 2
=> nil
And now the unexpected:
irb(main):004:0> def foo
irb(main):005:1> ios = IO.popen MaximaString
irb(main):006:1> ios.each_nonblock { |line| puts line }
irb(main):007:1> end
=> nil
irb(main):008:0> foo
*** rescued EAGAIN
=> nil
WTF? If I use “ls” instead of “maxima --batch-string=‘1+1;’” then it
works it
both cases. So is this a problem with Maxima, Ruby, or my code?
(Oh, and I know that non-blocking IO isn’t required for the specific
example
above, but I’d still like it to work to be more general in code I
haven’t
posted. And to understand why this is happening.)