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

**URL:** <https://www.ruby-forum.com/t/start-a-program-get-its-output-then-kill-it-while-multithreading/126456>\
**Category:** Ruby\
**Created:** [January 18, 2008, 11:31am UTC](https://www.ruby-forum.com/t/start-a-program-get-its-output-then-kill-it-while-multithreading/126456 "2008-01-18T11:31:20Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Deadolus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8491ac/32.png) [@Deadolus](https://www.ruby-forum.com/u/Deadolus)\
**Post date:** [January 18, 2008, 11:31am UTC](https://www.ruby-forum.com/t/start-a-program-get-its-output-then-kill-it-while-multithreading/126456/1 "2008-01-18T11:31:20Z")

</div>

Hi everybody,

i’d like to program a gui for iperf ([Best Open Source Mac Software 2023](http://sourceforge.net/projects/)  
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

---

<div class="post-metadata">

**Author:** ![Deadolus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8491ac/32.png) [@Deadolus](https://www.ruby-forum.com/u/Deadolus)\
**Post date:** [January 18, 2008, 11:57am UTC](https://www.ruby-forum.com/t/start-a-program-get-its-output-then-kill-it-while-multithreading/126456/2 "2008-01-18T11:57:09Z")

</div>

2008/1/18, Deadolus [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> 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

---

<div class="post-metadata">

**Author:** ![Deadolus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8491ac/32.png) [@Deadolus](https://www.ruby-forum.com/u/Deadolus)\
**Post date:** [January 18, 2008, 9:18pm UTC](https://www.ruby-forum.com/t/start-a-program-get-its-output-then-kill-it-while-multithreading/126456/3 "2008-01-18T21:18:49Z")

</div>

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

> 2008/1/18, Deadolus [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):
> 
> > …  
> > 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 🙂

---

<div class="post-metadata">

**Author:** ![Deadolus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8491ac/32.png) [@Deadolus](https://www.ruby-forum.com/u/Deadolus)\
**Post date:** [January 18, 2008, 7:57pm UTC](https://www.ruby-forum.com/t/start-a-program-get-its-output-then-kill-it-while-multithreading/126456/4 "2008-01-18T19:57:18Z")

</div>

On 18 Jan., 11:56, Robert K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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…

---

<div class="post-metadata">

**Author:** ![Deadolus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8491ac/32.png) [@Deadolus](https://www.ruby-forum.com/u/Deadolus)\
**Post date:** [January 19, 2008, 11:45am UTC](https://www.ruby-forum.com/t/start-a-program-get-its-output-then-kill-it-while-multithreading/126456/5 "2008-01-19T11:45:53Z")

</div>

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 🙂

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

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![Deadolus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8491ac/32.png) [@Deadolus](https://www.ruby-forum.com/u/Deadolus)\
**Post date:** [January 21, 2008, 11:02pm UTC](https://www.ruby-forum.com/t/start-a-program-get-its-output-then-kill-it-while-multithreading/126456/6 "2008-01-21T23:02:15Z")

</div>

On 19 Jan., 11:42, Robert K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

---

<div class="post-metadata">

**Author:** ![Deadolus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/8491ac/32.png) [@Deadolus](https://www.ruby-forum.com/u/Deadolus)\
**Post date:** [January 22, 2008, 4:36am UTC](https://www.ruby-forum.com/t/start-a-program-get-its-output-then-kill-it-while-multithreading/126456/7 "2008-01-22T04:36:53Z")

</div>

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/](http://drawohara.com/)
