While developing Tzunami (http://tzunami.sourceforge.net for the 
curious), I found an interesting issue with trying to wrap a timeout 
around a popen. When there is an uncooperative program in the popen, and 
a lot of data is being thrown at it, sometimes the Timeout thread locks 
up totally, along with the rest of my program.

What gets exciting is the results are completely dependant on the amount 
of data thrown at it, as well as the OS, as we will show below:

= cut here for sample code from http://profile.sh/hacks/popen-
timeout.rb ==
count = ARGV[0].to_i		# try 10,000 here to can it.
data = "X" * count		
f = IO.popen("/usr/bin/tail -f /etc/resolv.conf", 'w')
puts "1. popen done, filling with #{count} bytes of data"

$timeoutThread = Thread.new do
	sleep 5
	puts "3. Your time has come! You shall be ALRM'd"
	Process.kill "ALRM", $$
end

begin
	f.puts data
	puts "2. #{count} bytes of data sent, closing."
	f.close
	puts "4. popen closed"
rescue SignalException
	puts "5. Aborted - Caught signal!"
rescue SystemCallError
	puts "5. Error, my pipe probably closed"	
end

$timeoutThread.exit
puts "6. Successfully completed.
=========================================================

tail -f is just a demo of an 'uncooperative program', ie, one that will 
never end, no matter how much data we throw at it via stdin. Here is the 
output of the program, with 1000 as it's argument:

-- 1000 byte test ---------------------
1. popen done, filling with 1000 bytes of data
search nc.rr.com
nameserver 24.93.67.64
nameserver 24.93.67.65
2. 1000 bytes of data sent, closing.
3. Your time has come! You shall be ALRM'd
5. Aborted - Caught signal!
6. Successfully completed.

Perfect, no problems. Now, we make it 5000:

-- 10000 byte test ---------------------
1. popen done, filling with 10000 bytes of data
domain profile.sh
nameserver 24.93.67.64
nameserver 24.93.67.65
3. Your time has come! You shall be ALRM'd
5. Aborted - Caught signal!
6. Successfully completed.
<LOCK>

This I thought was interesting.. it would complete, but ruby would lock 
up at this point, and never exit. I couldn't reproduce this on FreeBSD 
4.4, but definitely reproducible in NetBSD 1.5Y and Darwin 1.4 (the byte 
values may differ).

-- 32000 byte test ---------------------
1. popen done, filling with 30000 bytes of data
domain profile.sh
nameserver 24.93.67.64
nameserver 24.93.67.65
<LOCK>

We lock here at a different point altogether, but lock indeed. 
Reproducible on FreeBSD (1.6.5), Darwin (1.6.5), NetBSD (1.6.4), but not 
AIX 4.3.3 (1.6.4) or IRIX 6.5 (1.6.5, but can't test >10k). Strange, eh?

/ Thomas Stromberg