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.
