It looks like that at least on MRI 1.8.7, the reader/writer ruby Sync
lock used in puppet file locking is not correctly thread safe.
Notably it is possible that:
* one writer thread sets the exclusive file lock
* another thread enters the read lock (which it shouldn't be able to do)
and calls flock for a shared lock.
* this has the effect of downgrading the file lock to a shared lock (this
is a property of posix flock).
* another process can now enter the write file lock part and corrupt the file.

This patch is a work-around to fix puppet file-locking, by using
a mutually exclusive critical section instead of r/w lock.

This patch doesn't address the other clients of P::Util.sync.

Signed-off-by: Brice Figureau <[email protected]>
---
 lib/puppet/util/file_locking.rb |   15 +++++++++++++--
 1 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/lib/puppet/util/file_locking.rb b/lib/puppet/util/file_locking.rb
index 8b194ed..629de3e 100644
--- a/lib/puppet/util/file_locking.rb
+++ b/lib/puppet/util/file_locking.rb
@@ -1,12 +1,23 @@
 require 'puppet/util'
+require 'thread'
+require 'monitor'
 
 module Puppet::Util::FileLocking
   module_function
 
+  @@mutexes = {}.extend(MonitorMixin)
+
+  def mutex(resource)
+    @@mutexes.synchronize do
+      @@mutexes[resource] ||= Mutex.new
+      @@mutexes[resource]
+    end
+  end
+
   # Create a shared lock for reading
   def readlock(file)
     raise ArgumentError, "#{file} is not a file" unless !File.exists?(file) or 
File.file?(file)
-    Puppet::Util.sync(file).synchronize(Sync::SH) do
+    mutex(file).synchronize do
       File.open(file) { |f|
         f.lock_shared { |lf| yield lf }
       }
@@ -33,7 +44,7 @@ module Puppet::Util::FileLocking
       end
     end
 
-    Puppet::Util.sync(file).synchronize(Sync::EX) do
+    mutex(file).synchronize do
       File.open(file, "w", mode) do |rf|
         rf.lock_exclusive do |lrf|
           yield lrf
-- 
1.7.2.1

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en.

Reply via email to