# IO not closed by GC

**URL:** <https://www.ruby-forum.com/t/io-not-closed-by-gc/58011>\
**Category:** Ruby\
**Created:** [April 17, 2006, 6:57pm UTC](https://www.ruby-forum.com/t/io-not-closed-by-gc/58011 "2006-04-17T18:57:13Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![pure](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/3ab097/32.png) [@pure](https://www.ruby-forum.com/u/pure)\
**Post date:** [April 17, 2006, 6:57pm UTC](https://www.ruby-forum.com/t/io-not-closed-by-gc/58011/1 "2006-04-17T18:57:13Z")

</div>

Hello,

I often use constructions like the following:

os = IO.popen(‘uname -sr’).readlines.to\_s.strip

I assume that the Garbage Collector throws away the IO instance created  
by IO::popen, because it’s simply not needed after that line anymore.

What I’ve experienced is, that it leaves a zombie for each time I use  
such an instruction.

* * *

loop {  
zombies = IO.popen(‘ps ax|grep defunct|wc -l’).readlines.to\_s.strip  
puts “Number of zombies: #{zombies}”  
}

* * *

This code produces about 100 defunct processes in about 2 seconds.  
Operating system is FreeBSD 6.1-RC.

However, if I close the IO object manually, defunct processes stay  
constantly at 2-3.

* * *

loop {  
io = IO.popen(‘ps ax|grep defunct|wc -l’)  
zombies = io.readlines.to\_s.strip  
io.close  
puts “Number of zombies: #{zombies}”  
}

* * *

Is this assumed behaviour or a bug? I guess there’s a close(2) or  
waitpid(2) missing in the IO code…

Stephan.

---

<div class="post-metadata">

**Author:** ![pure](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/3ab097/32.png) [@pure](https://www.ruby-forum.com/u/pure)\
**Post date:** [April 17, 2006, 8:05pm UTC](https://www.ruby-forum.com/t/io-not-closed-by-gc/58011/2 "2006-04-17T20:05:06Z")

</div>

On Apr 17, 2006, at 6:55 PM, Stephan M. wrote:

> Is this assumed behaviour or a bug? I guess there’s a close(2) or  
> waitpid(2) missing in the IO code…

See ``ri IO#close’’. Use the block form if you do not want to call  
close manually.

> os = IO.popen(‘uname -sr’).readlines.to\_s.strip

Calling IO#readlines.to\_s is a rather indirect way of calling IO#read.

Try:

```
 os = `uname -sr`.strip

```

or

```
 os = %x{uname -sr}.strip

```

– Daniel
