Provides an interface for acquiring and releasing a system-wide exclusive lock.
Used by Chef::Client to ensure only one instance of chef-client (or solo) is modifying the system at a time.
Create a new instance of RunLock
:lockfile: |
the full path to the lockfile. |
# File lib/chef/run_lock.rb, line 45 def initialize(lockfile) @runlock_file = lockfile @runlock = nil @mutex = nil @runpid = nil end
Acquire the system-wide lock. Will block indefinitely if another process already has the lock and Chef::Config is not set. Otherwise will block for Chef::Config seconds and exit if the lock is not acquired.
Each call to acquire should have a corresponding call to release.
The implementation is based on File#flock (see also: flock(2)).
Either acquire() or test() methods should be called in order to get the ownership of run_lock.
# File lib/chef/run_lock.rb, line 63 def acquire if timeout_given? begin Timeout::timeout(time_to_wait) do unless test if time_to_wait > 0.0 wait else exit_from_timeout end end end rescue Timeout::Error => e exit_from_timeout end else wait unless test end end
Release the system-wide lock.
# File lib/chef/run_lock.rb, line 135 def release if runlock if Chef::Platform.windows? mutex.release else runlock.flock(File::LOCK_UN) end runlock.close # Don't unlink the pid file, if another chef-client was waiting, it # won't be recreated. Better to leave a "dead" pid file than not have # it available if you need to break the lock. reset end end
# File lib/chef/run_lock.rb, line 125 def save_pid runlock.truncate(0) runlock.rewind # truncate doesn't reset position to 0. runlock.write(Process.pid.to_s) # flush the file fsync flushes the system buffers # in addition to ruby buffers runlock.fsync end
Tests and if successful acquires the system-wide lock. Returns true if the lock is acquired, false otherwise.
Either acquire() or test() methods should be called in order to get the ownership of run_lock.
# File lib/chef/run_lock.rb, line 89 def test # ensure the runlock_file path exists create_path(File.dirname(runlock_file)) @runlock = File.open(runlock_file,'a+') if Chef::Platform.windows? acquire_win32_mutex else # If we support FD_CLOEXEC, then use it. # NB: ruby-2.0.0-p195 sets FD_CLOEXEC by default, but not # ruby-1.8.7/1.9.3 if Fcntl.const_defined?('F_SETFD') && Fcntl.const_defined?('FD_CLOEXEC') runlock.fcntl(Fcntl::F_SETFD, runlock.fcntl(Fcntl::F_GETFD, 0) | Fcntl::FD_CLOEXEC) end # Flock will return 0 if it can acquire the lock otherwise it # will return false if runlock.flock(File::LOCK_NB|File::LOCK_EX) == 0 true else false end end end
Generated with the Darkfish Rdoc Generator 2.