I've tested this program on linux boxes with 1 and 2 processors, but on 
a SunOS 5.7 quad cpu there are apparently problems with flock.

$ ruby -v
1.7.3 (2002-10-30) [sparc-solaris2.7]

The program forks n child processes which attempt to read and write a 
marshalled object in /tmp/foo.

It's fine on sunos with n=1. It's fine on linux (single cpu and dual cpu 
SMP) with n=1,2,20. But it fails with n=2 on sunos 5.7.

The only explanation I can think of is that flock is not preventing the 
two processes from simultaneously accessing the file. Hope I'm wrong...

====================

class TestObject
   attr_accessor :x
   def initialize
     @x = 0
     @random_stuff = (0..rand(10)).map {|i| i}
       # so the object has variable size
   end
end

$path = '/tmp/foo'
process_count =    2
rep_count     =  1000

File.open($path, "w") do |f|
   Marshal.dump(TestObject.new, f)
end

(0...process_count).map do
   fork do
     rep_count.times do
       File.open($path, "r+") do |f|
         begin
           f.flock(File::LOCK_EX)

           str = f.read
           begin
             tester = Marshal.load(str)
           rescue ArgumentError => e
             puts e
             p str
             exit!
           end

           case 2  # 1 or 2 both cause the problem
           when 1
             File.read($path)

             new_tester = TestObject.new
               # will probably have different size

             tester = new_tester
               # commenting out this line fixes problem

             f.rewind
             Marshal.dump(tester, f)
             f.truncate(f.pos)

           when 2
             File.read($path)

             f.rewind
             f.truncate(0)
               # This ^^^ line (*) seems to cause the problem
             Marshal.dump(tester, f)
             #f.truncate(f.pos)
               # doing this ^^^ instead of (*) fixes it

           end

         ensure
           f.flush
           f.flock(File::LOCK_UN)
         end
       end
     end
   end
end

monitor_thread = Thread.new do
   i = 0
   loop do
     puts "Clock: #{i} seconds"
     sleep 1
     i += 1
   end
end

(0...process_count).each do
   Process.wait
end