Start a program, get it's output, then kill it. while "multithreading"

Hi everybody,

i’d like to program a gui for iperf (Best Open Source Mac Software 2023
iperf), it should run under windows And *NIX and I’m using fox as my
gui toolkit, I’ll use some extra calculations to get the parameters,
that’s why I can’t use an already existing gui for iperf.
I already designed the gui and I’m now moving to connect the different
widgets to it’s functions.
After you set all your parameters (size of packet, bandwith,
time, …) I want to press a button and it should start iperf and
parallely read the it’s output, so I can display some statistics
(running time and, on server side, the packet loss, maybe more).
So what should I program to do this?
I read about multithreading, IO.popen would be perfect, but how can I
kill iperf when I want to quit, before iperf ran out of time?
I think threads could also work (especially because one can kill
threads, if no longer used so the program would be terminated), but
what do I do to start the iperf?
I’m new to this subject and would appreciate any help on this!

Thanks in advance,

Deadolus

2008/1/18, Deadolus [email protected]:

So what should I program to do this?
I read about multithreading, IO.popen would be perfect, but how can I
kill iperf when I want to quit, before iperf ran out of time?
I think threads could also work (especially because one can kill
threads, if no longer used so the program would be terminated), but
what do I do to start the iperf?

First of all killing a thread won’t help because the process is in no
way attached to a Ruby thread (btw, this would also be true if Ruby
was using native threads).

You can however use a thread to read output from IO.popen. For
example, you could stuff lines into a Queue which is read from your UI
thread and displayed. Or whatever you want do do with it.

About the killing I am not sure. With a quick check I did not find a
proper way to get the PID of the child process with IO.popen. If
there is no way you could use popen with “-” as command (i.e. start a
child process), have that writ out the current PID (in $$) to stdout
and exec the process you want to start. The parent would then have to
read the child PID first and remember it somewhere.

Kind regards

robert

On Fri, Jan 18, 2008 at 07:56:34PM +0900, Robert K. wrote:

2008/1/18, Deadolus [email protected]:


I read about multithreading, IO.popen would be perfect, but how can I
kill iperf when I want to quit, before iperf ran out of time?

About the killing I am not sure. With a quick check I did not find
a proper way to get the PID of the child process with IO.popen. If

It’s a little hard to find until you already know where it is, but
IO#pid might come in handy here :slight_smile:

On 18 Jan., 11:56, Robert K. [email protected] wrote:

After you set all your parameters (size of packet, bandwith,
First of all killing a thread won’t help because the process is in no
child process), have that writ out the current PID (in $$) to stdout
and exec the process you want to start. The parent would then have to
read the child PID first and remember it somewhere.

Kind regards

robert


use.inject do |as, often| as.you_can - without end

I think I found the solution, this is a example script:

io = IO.popen(“ping google.ch”) #open a new io
thread = Thread.new(io) {while !io.closed? do Thread.current[“line”] =
io.readline end}#ALWAYS read current line of io
i=0 #example code…
while i<10 do
puts thread[“line”]
puts thread.status #puts out “sleep”, so it’s running…
i+=1
sleep(1)
end
io.close #close io
thread.status #puts out “nil” so it’s terminated

Seems like you easily can close a io just by “close”.
At least it isn’t in my ps aux list any more…
But I just tested under linux so far, so I can’t say if this also
works under windows (I currently have some problems with my windows
box).
What do you think about this solution?
If anyone has a better solution, I’m still interested…

On 18.01.2008 21:18, Stephen L. wrote:

It’s a little hard to find until you already know where it is, but
IO#pid might come in handy here :slight_smile:

Thanks! I use #popen too infrequently and when I use it I do not
normally fiddle with the process directly.

Kind regards

robert

On 19 Jan., 11:42, Robert K. [email protected] wrote:

a proper way togetthe PID of the child process with IO.popen. If
robert
I wasn’t really happy about my solution, so I continued
experimenting.
I now have something, which I’m quite happy about, I’ll post it here,
maybe some people have the same problems as I had.
I expanded the normal IO class:

#-------------------File
OwnIO.rb--------------------------------------
module OwnIO

def killed? #nil if not killed, pid of IO if killed
#I think we do not need this, please correct me, if I am wrong:
#if(self.class != IO) then raise “Wrong type of Input variable, is
#{self.class} but should be IO!” end
begin

  Process.waitpid(self.pid,Process::WNOHANG)
rescue Errno::ECHILD #rescue if process is already terminated
  self.pid
end

end

def kill #kill a IO (you still have to close it)
Process.kill(“KILL”,self.pid)
end

end

class IO #add my own IO module to the normal IO class
include OwnIO
end

#---------EOF----------------------------------------------

And here is a short example script (how I’ll implement it in my GUI
more or less):

#-------------------test.rb---------------------------------
require “OwnIO.rb”
STDOUT.sync = true
old = nil #old output
i = 0
io = IO.popen(“ping google.ch”)
io.sync = true

t = Thread.new() {while !io.killed? do Thread.current[“line”] =
io.readline end}#first doesn’t output all lines (Thread creation too
slow?)
while !io.killed? do
if t[“line”]!=old then#only react to changes of the line
old = t[“line”]
puts t[“line”]#puts the current line
if i==20 then ##kill the io after 20 lines have been received
io.kill
end
i+=1;
end
end
puts “Killed”
#----------------------------
EOF----------------------------------------

The two functions “killed?” and “kill” are self explanatory, and seem
to work nice.
But at least “killed?” could have some improvements…
So if anybody has some improvements/suggestions to the code: go ahead!

Regards, Deadolus

On Jan 21, 2008, at 2:59 PM, Deadolus wrote:

So if anybody has some improvements/suggestions to the code: go ahead!

if you care about stderr this won’t work on windows or nix. threads,
io, and guis will hang you on windows unless you really know what you
are doing. for a portable way to start a process, capture it’s
stdout/stderr, and have a handle on the pid see my systemu lib - it’s
the only thing that’ll work afaikt (read archives)

regards.

a @ http://drawohara.com/