Class: Chef::RunLock
- Includes:
- Mixin::CreatePath
- Defined in:
- lib/chef/run_lock.rb
Overview
Chef::RunLock
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.
Instance Attribute Summary collapse
-
#runlock ⇒ Object
readonly
Returns the value of attribute runlock.
-
#runlock_file ⇒ Object
readonly
Returns the value of attribute runlock_file.
Instance Method Summary collapse
-
#acquire ⇒ Object
Acquire the system-wide lock.
-
#initialize(config) ⇒ RunLock
constructor
- Create a new instance of RunLock === Arguments * config:
-
This will generally be the
Chef::Config, but any Hash-like object with Symbol keys will work.
-
#release ⇒ Object
Release the system-wide lock.
Methods included from Mixin::CreatePath
Constructor Details
#initialize(config) ⇒ RunLock
Create a new instance of RunLock
Arguments
- config:
-
This will generally be the
Chef::Config, but any Hash-like
object with Symbol keys will work. See ‘Parameters’ section.
Parameters/Config
- :lockfile:
-
if set, this will be used as the full path to the lockfile.
- :file_cache_path:
-
if
:lockfileis not set, the lock file will be
named “chef-client-running.pid” and be placed in the directory given by
:file_cache_path
44 45 46 47 |
# File 'lib/chef/run_lock.rb', line 44 def initialize(config) @runlock_file = config[:lockfile] || "#{config[:file_cache_path]}/chef-client-running.pid" @runlock = nil end |
Instance Attribute Details
#runlock ⇒ Object (readonly)
Returns the value of attribute runlock.
32 33 34 |
# File 'lib/chef/run_lock.rb', line 32 def runlock @runlock end |
#runlock_file ⇒ Object (readonly)
Returns the value of attribute runlock_file.
33 34 35 |
# File 'lib/chef/run_lock.rb', line 33 def runlock_file @runlock_file end |
Instance Method Details
#acquire ⇒ Object
Acquire the system-wide lock. Will block indefinitely if another process already has the lock.
Each call to acquire should have a corresponding call to #release.
The implementation is based on File#flock (see also: flock(2)).
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/chef/run_lock.rb', line 55 def acquire # ensure the runlock_file path exists create_path(File.dirname(runlock_file)) @runlock = File.open(runlock_file,'w+') # if we support FD_CLOEXEC (linux, !windows), 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 unless runlock.flock(File::LOCK_EX|File::LOCK_NB) # Another chef client running... runpid = runlock.read.strip.chomp Chef::Log.warn("Chef client #{runpid} is running, will wait for it to finish and then run.") runlock.flock(File::LOCK_EX) end # We grabbed the run lock. Save the pid. runlock.truncate(0) runlock.rewind # truncate doesn't reset position to 0. runlock.write(Process.pid.to_s) end |
#release ⇒ Object
Release the system-wide lock.
77 78 79 80 81 82 83 84 85 86 |
# File 'lib/chef/run_lock.rb', line 77 def release if runlock runlock.flock(File::LOCK_UN) 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 |