The ruby interpreter tries very hard to map blocking syscalls to their non-blocking counterparts (for example, all I/Os are passed to a select() call). This gets really dirty when you mix I/O and other syscalls. For example, see the strace output the following Ruby code:
require ‘thread’
th1 = Thread::new do
pid = fork sleep 2
Process::waitpid(pid)
puts “Finished.”
end
th2 = Thread::new do
f = STDIN.read
puts “Finished2.”
end
th1.join
select(1, [0], [], [], 0, 349 ) = 0 (Timeout)
gettimeofday( 1168847486, 478832 , NULL) = 0
select(1, [0], [], [], 0, 0 ) = 0 (Timeout)
waitpid(25249, 0xbf926810, WNOHANG) = 0
select(1, [0], [], [], 0, 0 ) = 0 (Timeout)
gettimeofday( 1168847486, 479013 , NULL) = 0
gettimeofday( 1168847486, 479053 , NULL) = 0
select(1, [0], [], [], 0, 59959 ) = 0 (Timeout)
gettimeofday( 1168847486, 538971 , NULL) = 0
select(1, [0], [], [], 0, 41 ) = 0 (Timeout)
gettimeofday( 1168847486, 543017 , NULL) = 0
select(1, [0], [], [], 0, 0 ) = 0 (Timeout)
waitpid(25249, 0xbf926810, WNOHANG) = 0
select(1, [0], [], [], 0, 0 ) = 0 (Timeout)
gettimeofday( 1168847486, 543200 , NULL) = 0
gettimeofday( 1168847486, 543240 , NULL) = 0
select(1, [0], [], [], 0, 59959 ) = 0 (Timeout)
gettimeofday( 1168847486, 602842 , NULL) = 0
select(1, [0], [], [], 0, 357 ) = 0 (Timeout)
gettimeofday( 1168847486, 606842 , NULL) = 0
select(1, [0], [], [], 0, 0 ) = 0 (Timeout)