Non-blocking IO & Maxima

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© } # 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 © Bruno Haible, Michael Stoll 1992, 1993
Copyright © Bruno Haible, Marcus Daniels 1994-1997
Copyright © Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
Copyright © 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.)

In article [email protected],
Jesse M. [email protected] writes:

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?

I think it is caused by that maxima is slower than ls.

Try “sleep 1; ls”.

It is impossible to read a line before a line is sent in
non-blocking manner.

On Saturday 23 June 2007 21:26, Tanaka A. wrote:

It is impossible to read a line before a line is sent in
non-blocking manner.

Ah, thats it, thanks. I wasn’t thinking about the delay between typing
lines
in IRB that gave it the time to execute…