Thursday, February 11, 2016

PowerShell : Use Case for MutEx

This post is to give you context on a practical use case of using MutEx in PowerShell.

From the MSDN documentation for the MutEx class , MutEx is :


"A synchronization primitive that can also be used for interprocess synchronization."


Mut - Mutually 
Ex - Exclusive


Recently while deploying AzureStack, I saw multiple failed deployments, partly because of me not paying attention. 


But since it failed, I had to go and look at the code in an effort to see what went wrong.

AzureStack runs all the deployment tasks for creating a POC by using scheduled tasks (runs in System context) heavily.

Also the status of the deployment  is tracked by using XML files (these are placed under C:\ProgramData\Microsoft\AzureStack\), so they have to avoid conflicts in reading and writing of these XML files from these tasks which are separate PowerShell processes.

Now this is a simple but very important part of the whole process. So while going through the code being used,
I saw this little neat function in the AzureStakDeploymentStatus.psm1 file :


001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
## Lock the status reads\writes with a mutex to avoid conlicts
function Invoke-ActionWithMutex
{
    param(
        [ScriptBlock]$Action
    )

    $mutex = $null

    try
    {
        $createdNew = $fasle # Typo here but this evaluates to False

        $mutex = New-Object System.Threading.Mutex($true, "Global\AzureStackDeploymentStatus", [ref]$createdNew)

        if (-not $createdNew)
        {
            try
            {
               $mutex.WaitOne() | Out-Null
            }
            catch [System.Threading.AbandonedMutexException]
            {
                #AbandonedMutexException means another thread exit without releasing the mutex, and this thread has acquired the mutext, therefore, it can be ignored
            }
        }

        Invoke-Command -ScriptBlock $Action -NoNewScope
    }
    finally
    {
        if ($mutex -ne $null)
        {
            $mutex.ReleaseMutex()
            $mutex.Dispose()
        }
    }

}

This function piqued my interest on the subject of MutEx. In the same .psm1 file this function is being used within the functions Get-AzureStackDeploymentStatus and Update-AzureStackDeploymentStatus.

Below is the Get-AzureStackDeploymentStatus defintion :


001
002
003
004
005
006
007
008
009
010
011
012
function Get-AzureStackDeploymentStatus
{
    [CmdletBinding()]
    param()
    if (-not (Test-Path $statusFilePath)) {
        Update-AzureStackDeploymentStatus $StatusTemplate | Out-Null
    }

    Invoke-ActionWithMutex -Action {
        [xml](Get-Content $statusFilePath)
    }
}

and the Update-AzureStackDeploymentStatus definition is below:


001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
function Update-AzureStackDeploymentStatus
{
    [CmdletBinding()]
    param(
        [Xml]$Status
    )

    Invoke-ActionWithMutex -Action {
        if (-not (Test-Path $statusFileFolder))
        {
            New-Item -Path $statusFileFolder -ItemType Directory | Out-Null
        }
        $Status.Save($statusFilePath)
    }
}


Now this is powerful stuff and since my first exposure to it, I have been reading up a lot on this topic and how to use this in my Scripts.

This post will soon follow a series of post on this particular topic.

No comments:

Post a Comment