diff options
author | sersut <serdar@opscode.com> | 2013-10-25 04:11:58 -0700 |
---|---|---|
committer | sersut <serdar@opscode.com> | 2013-10-25 04:11:58 -0700 |
commit | be67ca1217fde4fce8f1d94870fc0c8d4ec943d7 (patch) | |
tree | 8e4882fc5dffc936b20909ebeaa20957037037e6 | |
parent | 667f072ac6eb764d39708aae2f304f031b98d0ce (diff) | |
download | chef-be67ca1217fde4fce8f1d94870fc0c8d4ec943d7.tar.gz |
Check before creating a new system mutex on windows.
This is needed when multiple user accounts are running chef-client on systems. This scenario is imminent when they configure chef to run as service on windows which by default runs as "Local System" and when they try to run chef client manually as Administrator.
NOTE: Non-admin users do not wait on the run_lock but can create a run_lock if there is not one already.
-rw-r--r-- | lib/chef/client.rb | 6 | ||||
-rw-r--r-- | lib/chef/win32/mutex.rb | 45 |
2 files changed, 33 insertions, 18 deletions
diff --git a/lib/chef/client.rb b/lib/chef/client.rb index 30b714cded..837f8ad432 100644 --- a/lib/chef/client.rb +++ b/lib/chef/client.rb @@ -471,6 +471,10 @@ class Chef # === Returns # true:: Always returns true. def do_run + # Check for windows administrator rights incase they create an + # issue while trying to create / acquire run_lock. + do_windows_admin_check + runlock = RunLock.new(Chef::Config.lockfile) runlock.acquire # don't add code that may fail before entering this section to be sure to release lock @@ -493,8 +497,6 @@ class Chef Chef::Log.info("Starting Chef Run for #{node.name}") run_started - do_windows_admin_check - run_context = setup_run_context converge(run_context) diff --git a/lib/chef/win32/mutex.rb b/lib/chef/win32/mutex.rb index b0a9ba210e..3ca0c97ef2 100644 --- a/lib/chef/win32/mutex.rb +++ b/lib/chef/win32/mutex.rb @@ -22,25 +22,10 @@ class Chef module ReservedNames::Win32 class Mutex include Chef::ReservedNames::Win32::API::Synchronization - extend Chef::ReservedNames::Win32::API::Synchronization def initialize(name) @name = name - # First check if there exists a mutex in the system with the - # given name. - - # In the initial creation of the mutex initial_owner is set to - # false so that mutex will not be acquired until someone calls - # acquire. - # In order to call "*W" windows apis, strings needs to be - # encoded as wide strings. - @handle = CreateMutexW(nil, false, name.to_wstring) - - # Fail early if we can't get a handle to the named mutex - if @handle == 0 - Chef::Log.error("Failed to create system mutex with name'#{name}'") - Chef::ReservedNames::Win32::Error.raise! - end + create_system_mutex end attr_reader :handle @@ -87,6 +72,34 @@ if the mutex is attempted to be acquired by other threads.") Chef::ReservedNames::Win32::Error.raise! end end + + private + + def create_system_mutex + # First check if there exists a mutex in the system with the + # given name. We need only synchronize rights if a mutex is + # already created. + # InheritHandle is set to true so that subprocesses can + # inherit the ownership of the mutex. + @handle = OpenMutexW(SYNCHRONIZE, true, name.to_wstring) + + if @handle == 0 + # Mutext doesn't exist so create one. + # In the initial creation of the mutex initial_owner is set to + # false so that mutex will not be acquired until someone calls + # acquire. + # In order to call "*W" windows apis, strings needs to be + # encoded as wide strings. + @handle = CreateMutexW(nil, false, name.to_wstring) + + # Looks like we can't create the mutex for some reason. + # Fail early. + if @handle == 0 + Chef::Log.error("Failed to create system mutex with name'#{name}'") + Chef::ReservedNames::Win32::Error.raise! + end + end + end end end end |