How to tell when IO::popen is finished?

Hi,

I’ve just installed and had some success with the gnuplot library.

I’m saving the output to a png file (plot.terminal “png”) and this all
works
well, but when I try to use the file it isn’t finished writing it yet
and I
get an exception.

I’ve used

Gnuplot.open( ) do |gp|

end

while(!File.exists?("/test2.png") || File.zero?("/test2.png") )
sleep 0.1
end

In an attempt to wait until the file is written before I try to do
anything
with it, but this seems a bit too hackish.

Can I capture the Gnuplot.open into a variable and check it? The last
statement in the Gnuplot.open is a call to
IO::popen( cmd, “w”) { |io| yield io }

but if I test the class of what is returned it is
Gnuplot::Plot

not anything to do with IO

Is there a way that I can test the IO::popen to tell when it’s finished?

On Thu, 3 Aug 2006, Daniel N wrote:

Gnuplot.open( ) do |gp|
Can I capture the Gnuplot.open into a variable and check it? The last
statement in the Gnuplot.open is a call to
IO::popen( cmd, “w”) { |io| yield io }

but if I test the class of what is returned it is
Gnuplot::Plot

not anything to do with IO

Is there a way that I can test the IO::popen to tell when it’s finished?

can you show the code? that pipe will be automatically closed once the
yield
has returned.

-a

On 8/4/06, [email protected] [email protected] wrote:

and I

end
Gnuplot::Plot

-a

we can never obtain peace in the outer world until we make peace with
ourselves.

  • h.h. the 14th dali lama

I’m using Gnuplot the open method is

def Gnuplot.open( persist=true )
cmd = Gnuplot.gnuplot( persist ) or raise ‘gnuplot not found’
IO::popen( cmd, “w”) { |io| yield io }
end

Then my method

def make_chart( )
Gnuplot.open() do |gp|
Gnuplot::Plot.new(gp) do |plot|
plot.terminal “png”
plot.output “/test2.png”

plot.title  "Array Plot Example"
plot.ylabel "x"
plot.xlabel "x^2"

x = (0..200).collect { |v| v.to_f }
y = x.collect { |v| v ** 2 }

plot.data << Gnuplot::DataSet.new( [x, y] ) do |ds|
  ds.with = "lines"
  ds.notitle
  ds.linewidth = 6

end

end

end
end

make_chart

while(!File.exists?(“/test2.png”) || File.zero?(“/test2.png”) )
sleep 0.1
end

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

If the IO::popen is creating a child process, how about calling
Process.waitpid? Once that returns, the subprocess will have
completed and the file should be complete.

Cheers,
Chris

On 03 Aug 2006, at 6:29 AM, Daniel N wrote:

I’ve used
anything

Is there a way that I can test the IO::popen to tell when it’s
finished?

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (Darwin)

iD8DBQFE0gh+rOGxDZoCCzURAuTIAKDYiSODiBkrNJRa16V/VzSybhLb/wCgm/7C
BgaaVLCVUlngxwov8RNO8JY=
=qb5q
-----END PGP SIGNATURE-----

On 8/4/06, Christopher B. [email protected] wrote:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

If the IO::popen is creating a child process, how about calling
Process.waitpid? Once that returns, the subprocess will have
completed and the file should be complete.

Cheers,
Chris

How would I get the pid that the child process is on?

On Thu, 3 Aug 2006, Daniel N wrote:

I’m using Gnuplot the open method is

this works fine on my box:

 harp:~ > cat a.rb
 require 'rubygems'
 require 'gnuplot'

 PNG = ARGV.shift || 'test.png'

 def Gnuplot.open( persist=true )
   cmd = Gnuplot.gnuplot( persist ) or raise 'gnuplot not found'
   IO::popen( cmd, "w") { |io| yield io }
 end


 def make_chart( )
 Gnuplot.open() do |gp|
   Gnuplot::Plot.new(gp) do |plot|
     plot.terminal  "png"
     plot.output  PNG

     plot.title  "Array Plot Example"
     plot.ylabel "x"
     plot.xlabel "x^2"

     x = (0..200).collect { |v| v.to_f }
     y = x.collect { |v| v ** 2 }

     plot.data << Gnuplot::DataSet.new( [x, y] ) do |ds|
       ds.with = "lines"
       ds.notitle
       ds.linewidth = 6

     end
   end

 end
 end

 make_chart

 p File.stat(PNG)

 # works if you have image magick installed
 system "display #{ PNG }"


 harp:~ > ruby a.rb
 #<File::Stat dev=0x306, ino=33786, mode=0100664, nlink=1, uid=447, 

gid=447, rdev=0x51e1, size=3583, blksize=4096, blocks=8, atime=Thu Aug
03 08:53:07 MDT 2006, mtime=Thu Aug 03 08:53:50 MDT 2006, ctime=Thu Aug
03 08:53:50 MDT 2006>

i think your issue was ‘/test2.png’ - unless you’re root i doubt you can
open
that file.

regards.

-a

On 8/4/06, [email protected] [email protected] wrote:

 require 'rubygems'
 def make_chart( )
     y = x.collect { |v| v ** 2 }
 end
 #<File::Stat dev=0x306, ino=33786, mode=0100664, nlink=1, uid=447,

-a

we can never obtain peace in the outer world until we make peace with
ourselves.

  • h.h. the 14th dali lama

I’m on windows :slight_smile: I don’t need root. Ohhh gives me goosebumps :wink:

The problem isn’t that the file isn’t created. It’s just that I don’t
know
when it’s finished being written.

I want to incorporate this into an app but I don’t want to go trying to
grab
the image if it doenst exist yet.

I’m not quite sure how your using PNG in your code above. Is this a
constant of gnuplot?

On Aug 3, 2006, at 10:40 AM, Daniel N wrote:

Chris

How would I get the pid that the child process is on?

You could just use Process.waitall (Or Process.wait() if you’re
feeling lucky)

On Fri, Aug 04, 2006 at 08:19:48AM +0900, Daniel N wrote:

I’m on windows :slight_smile: I don’t need root. Ohhh gives me goosebumps :wink:

Well . . . technically, you’re already root (or its equivalent).

?? it’s set to the first command line parameter

 harp:~ > cat a.rb
 require 'rubygems'
 require 'gnuplot'

 PNG = ARGV.shift || 'test.png'

it can be anything you like.

you have one of two problems:

  • /test2.png is being interpreted as some sort of switch. definitely
    try
    without the leading slash - that’s a bizarre filename anyhow…

  • the gnuplot exe is not being found in your PATH. search the
    archives -
    i’ve solved this one before.

regards.

-a

On 8/4/06, Daniel N [email protected] wrote:

to

 require 'rubygems'

try

/test2.png, bizarre as it is, is created correctly at c:\test2.png and I
chart_file = File.open( ‘c:/test2.png’ ) #< raises and exception because
the
file does not yet exist

I would have thought that since Gnuplot.open has IO::popen as it’s last
statement it would return some kind of IO object, but it returns a
Gnuplot::Plot object.

Sorry if I’m going around circles. I appreciate your help with this.

Daniel

I’m really trying to grok how this works.

In the docs for IO it says that the block will return the results of the
block, not an IO object. Sorry I didn’t pick this up earilier.

The other thing that I found in there, I think, was that when the pipe
is
opened, the ruby side of the pipe evaluates the block, sends its results
and
then closes.

I guess this is why I’m having trouble. Ruby executes the block and
closes
then moves onto the next statment, but gnuplot, on the other end of the
pipe
is still doing it’s thing drawing the chart. If it doesn’t finish
before
the ruby moves on I get the exception.

Am I understanding this correctly? If I am, is there any way to get at
the
process that gnuplot is running so I can tell when it’s finished?

Cheers

Daniel

On 8/4/06, [email protected] [email protected] wrote:

 PNG = ARGV.shift || 'test.png'
  • the gnuplot exe is not being found in your PATH. search the archives
  • i’ve solved this one before.

regards.

-a

happiness is not something ready-made. it comes from your own actions.

  • h.h. the 14th dali lama

Sorry Ara, I must be really thick at this because I don’t understand,
except
the PNG part… whoops :wink:

The chart is created, so the exe is found and executed.

/test2.png, bizarre as it is, is created correctly at c:\test2.png and I
can
open it no problem once its written.

The issue is that when I call make_chart and then immediately try to do
something with c:\test2.png it doesn’t exist yet. I need to wait for it
to
be written.

eg
make_chart
chart_file = File.open( ‘c:/test2.png’ ) #< raises and exception because
the
file does not yet exist

I would have thought that since Gnuplot.open has IO::popen as it’s last
statement it would return some kind of IO object, but it returns a
Gnuplot::Plot object.

Sorry if I’m going around circles. I appreciate your help with this.

Daniel

On Aug 3, 2006, at 7:19 PM, Daniel N wrote:

I’m on windows :slight_smile: I don’t need root. Ohhh gives me goosebumps :wink:

The problem isn’t that the file isn’t created. It’s just that I
don’t know
when it’s finished being written.

I want to incorporate this into an app but I don’t want to go
trying to grab
the image if it doenst exist yet.

It is possible that the OS is simply not yet finished writing the
file to disk. In unix this is forced by calling fsync (or sync on the
command line). I’ve got no idea what you do in windows.

The first thing to try is to find out what the windows equivalent of
the command line ‘sync’ and run it before trying to open the png. If
that works then you can get fancy…

Assuming the CL sync worked… In ruby the IO class has two methods
defined: fsync which is defined on an instance of the class, and sync
which is defined on the class. IO.sync won’t do what you need, it
just forces ruby to write its buffers. You can try opening the png
file and calling fsync from there, don’t know if that will work.
Alternatively, check to see of gnuplot will either give you the IO
object somehow or can be asked to fsync. If not, you might be able to
sneak into Gnuplot aliasing a method or re-opening the class or some
other trick and insert the fsync.

Cheers,
Bob

Bob H. – blogs at <http://www.recursive.ca/
hutch/>
Recursive Design Inc. – http://www.recursive.ca/
Raconteur – http://www.raconteur.info/
xampl for Ruby – http://rubyforge.org/projects/xampl/

On 8/6/06, Bob H. [email protected] wrote:

I want to incorporate this into an app but I don’t want to go

Cheers,
Bob

Bob H. – blogs at <http://www.recursive.ca/
hutch/>
Recursive Design Inc. – http://www.recursive.ca/
Raconteur – http://www.raconteur.info/
xampl for Ruby – http://rubyforge.org/projects/xampl/

Hi Bob.

Thanx very much for the information. I think I’ve got some homework to
do
:wink: