class Chef::ReservedNames::Win32::Mutex

Attributes

handle[R]
name[R]

Public Class Methods

new(name) click to toggle source
# File lib/chef/win32/mutex.rb, line 27
def initialize(name)
  @name = name
  create_system_mutex
end

Public Instance Methods

release() click to toggle source

Releases the mutex

# File lib/chef/win32/mutex.rb, line 72
      def release
        # http://msdn.microsoft.com/en-us/library/windows/desktop/ms685066(v=vs.85).aspx
        # Note that release method needs to be called more than once
        # if mutex is acquired more than once.
        unless ReleaseMutex(handle)
          # Don't fail things in here if we can't release the mutex.
          # Because it will be automatically released when the owner
          # of the process goes away and this class is only being used
          # to synchronize chef-clients runs on a node.
          Chef::Log.error("Can not release mutex '#{name}'. This might cause issues \
if other threads attempt to acquire the mutex.")
          Chef::ReservedNames::Win32::Error.raise!
        end
      end
test() click to toggle source

Attempts to grab the mutex. Returns true if the mutex is grabbed or if it's already owned; false otherwise.

# File lib/chef/win32/mutex.rb, line 39
def test
  WaitForSingleObject(handle, 0) == WAIT_OBJECT_0
end
wait() click to toggle source

Attempts to grab the mutex and waits until it is acquired.

# File lib/chef/win32/mutex.rb, line 45
def wait
  loop do
    wait_result = WaitForSingleObject(handle, 1000)
    case wait_result
    when WAIT_TIMEOUT
      # We are periodically waking up in order to give ruby a
      # chance to process any signal it got while we were
      # sleeping. This condition shouldn't contain any logic
      # other than sleeping.
      sleep 0.1
    when WAIT_ABANDONED
      # Previous owner of the mutex died before it can release the
      # mutex. Log a warning and continue.
      Chef::Log.trace "Existing owner of the mutex exited prematurely."
      break
    when WAIT_OBJECT_0
      # Mutex is successfully acquired.
      break
    else
      Chef::Log.error("Failed to acquire system mutex '#{name}'. Return code: #{wait_result}")
      Chef::ReservedNames::Win32::Error.raise!
    end
  end
end

Private Instance Methods

create_system_mutex() click to toggle source
# File lib/chef/win32/mutex.rb, line 89
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
    # Mutex 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