Non-blocking IO & Maxima

J

Jesse Merriman

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.)
 
T

Tanaka Akira

Jesse Merriman said:
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.
 
J

Jesse Merriman

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.


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

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,062
Latest member
OrderKetozenseACV

Latest Threads

Top