I’m trying to write an editor for ruby in ruby using the KDE4 bindings
for
ruby and I’m facing a problem which I don’t know whether is caused by
ruby or
by KDE. I want my editor to be able to run a ruby script and display
both the
error messages and the normal output in a window. The problem is that
all the
text sent to the standard output seems to be received together from my
application, and so does the text sent to standard error, even if the
two are
mixed. For example, when I run the following script
5.times do |i|
warn “Warning #{i}”
puts i
end
the output window of my program displays this:
Warning 0
Warning 1
Warning 2
Warning 3
Warning 4
0
1
2
3
4
instead of this (which is what I get if I run the script from terminal)
Warning 0
0
Warning 1
1
Warning 2
2
Warning 3
3
Warning 4
4
Since I don’t have much experience on interprocess communication, I
can’t, as
I said, understand if this issue is due to the way ruby prints its
output or
to the tools I use to run the ruby script from my editor, which are
specific
of KDE. I’d be glad if someone could give me a hint on this, so that at
least
I can know whether I have to look for documentation about ruby or about
KDE.
of KDE. I’d be glad if someone could give
me a hint on this, so that at least
I can know whether I have to look for
documentation about ruby or about
KDE.
It’s to do with buffering. Buffering takes place within Ruby (I think)
but also in the operating system. Stderr is usually unbuffered whereas
stdout is usually buffered. I.e. the output is accumulated in a memory
buffer until it reaches a certain size, then the block is flushed to the
output stream. This is a lot more efficient that outputting it
character-by-character to the output device.
In my experience (various languages and OSes), buffering can cause
problems that are difficult or impossible to resolve.
buffer until it reaches a certain size, then the block is flushed to the
output stream. This is a lot more efficient that outputting it
character-by-character to the output device.
In my experience (various languages and OSes), buffering can cause
problems that are difficult or impossible to resolve.
Thanks for the information. I think I’ll look at the source code of some
tool
which does what I want and see how it works.
but also in the operating system. Stderr is usually unbuffered
Thanks for the information. I think I’ll look at the source code of
some tool
which does what I want and see how it works.
Stefano
$stdout.sync = true; $stdout.flush
The #sync setting of true means “unbuffered” (sync’d to the
destination every time). If you build up messages, you can call #flush on the IO yourself instead.
The #sync setting of true means “unbuffered” (sync’d to the
destination every time). If you build up messages, you can call #flush on the IO yourself instead.
I don’t think that would work. If I understand correctly what you mean,
that
should be put in the script which produces the output, not not in the
one
displaying it. But since the output I want to display is from a script
written
by the user, I can’t do that.
I don’t think that would work. If I understand correctly what you
mean, that
should be put in the script which produces the output, not not in
the one
displaying it. But since the output I want to display is from a
script written
by the user, I can’t do that.
what you want to do is easily accomplished using session.rb
note that i wrote to do exactly what you are doing - but it was for
a tk gui. anyhow, you must do this in a background thread as there
are certain things child programs can do (like setvbuf) which can
defeat any counter buffering techniques you may try - so you must
always process the stdout/stderr asynchronously in a background thread
which updates the gui. session makes this trivial to accomplish.
we can deny everything, except that we have the possibility of being
better. simply reflect on that.
h.h. the 14th dalai lama
Thanks for telling me about session. Unfortunately, it still doesn’t
work. I
tried with the following code (there’s no ui because I wanted to
understand
how session works before using it in a more complex situation):
require ‘session’
t=Thread.new do
sh = Session.new
sh.execute( ‘ruby /home/stefano/documenti/scripts/prova.rb’ ) do |out,
err|
puts “Msg: #{out}” if out
puts “Err: #{err}” if err
end
end
t.join
The result is the same I already got, that is: all the error messages
together
and all the stdout messages together. At any rate, tried modifiying my
test
script:
$stdout.sync=true #added line
10.times{|i|
puts i
warn “Possible error #{i}”
sleep 1 #added line
}
With the introduction of the two lines marked with ‘added line’, the
output is
the one expected (even if it seems that the order in wich the error
message
and the stdout message are displayed for each iteration is random).
Removing
one of those lines brings it back to the ‘wrong’ behavior.
However, I’ve tried to run the same script using other editors
(kdevelop, scite, netbeans) and the results are the same as mine. This
seems
to mean that there’s not an easy way to accomplish what I want to do.