> I've just checked, and FreeBSD 8.2 is also affected by this issue.
> Test script:
> system("false")
> sleep 0.5
> th = Thread::new { $? }
> p th
> th.join
> p th
> p th.value

This is buggy. $? is thread local storage variable. last exit value
was set to main thread.
because system() was called from it. Therefore it fail even if run on linux.

In the other hand, on assert_normal_exit(), io.close is called from
sub thread. it's a source
of difference.
Please try following code. it work on linux.

io = IO.popen("false")
th = Thread.new {
  io.read
  io.close
  v = $?
  p v
  v
}
sleep 0.5

p th
th.join
p th
p th.value