2
Vote

SCSM Workflows - SMlets conflicts

description

Running SCSM 2012 SP1 UR4 with SMLets Beta 4 installed. Two SCSM PowerShell workflows (created with the Authoring Tool) that trigger upon Service Request creation.
Workflow 1 - PowerShell script modifies the activities contained in the SR.
Workflow 2 - PowerShell script modifies the SR itself.

Intermittently, both workflows will fail. This appears to happen when both workflows execute concurrently.
Outputting the error from both we see:

$error[0] | Format-List -Force | Out-String
Exception             : System.ArgumentException: Item has already been added. Key in dictionary: 'localhost'  Key being added: 'localhost' at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add) at SMLets.ConnectionHelper.GetMG(String computerName, PSCredential credential) in c:\Users\Administrator\Documents\WindowsPowerShell\CodePlex\smlets\Main\Source\SMLets\SMLets\Helper.cs:line 301 at SMLets.SMCmdletBase.BeginProcessing() in c:\Users\Administrator\Documents\WindowsPowerShell\CodePlex\smlets\Main\Source\SMLets\SMLets\Helper.cs:line 69
TargetObject          : localhost
CategoryInfo          : InvalidOperation: (localhost:String) [Get-SCSMClass], ArgumentException
FullyQualifiedErrorId : GenericMessage,SMLets.GetSMClassCommand
ErrorDetails          : 
InvocationInfo        : System.Management.Automation.InvocationInfo
PipelineIterationInfo : {0, 0}
PSMessageDetails      : 
$error[0].exception | format-list -force | Out-String
Message        : Item has already been added. Key in dictionary: 'localhost'  Key being added: 'localhost'
ParamName      : 
Data           : {}
InnerException : 
TargetSite     : Void Insert(System.Object, System.Object, Boolean)
StackTrace     :    at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add) at SMLets.ConnectionHelper.GetMG(String computerName, PSCredential credential) in c:\Users\Administrator\Documents\WindowsPowerShell\CodePlex\smlets\Main\Source\SMLets\SMLets\Helper.cs:line 301 at SMLets.SMCmdletBase.BeginProcessing() in c:\Users\Administrator\Documents\WindowsPowerShell\CodePlex\smlets\Main\Source\SMLets\SMLets\Helper.cs:line 69
HelpLink       : 
Source         : mscorlib
$error[0].exception.stacktrace | Out-String
   at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
   at SMLets.ConnectionHelper.GetMG(String computerName, PSCredential credential) in c:\Users\Administrator\Documents\WindowsPowerShell\CodePlex\smlets\Main\Source\SMLets\SMLets\Helper.cs:line 301
   at SMLets.SMCmdletBase.BeginProcessing() in c:\Users\Administrator\Documents\WindowsPowerShell\CodePlex\smlets\Main\Source\SMLets\SMLets\Helper.cs:line 69

comments

psikic wrote Dec 21, 2014 at 3:11 PM

We are having this issue too. We are running in Service Management Automation. If we have two runbooks (PowerShell Workflows) that try to connect to a MG at the same time, one of them fails.

Item has already been added. Key in dictionary: '(SCSM Server name)' Key being added:
'(SCSM Server name)'
at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
at SMLets.ConnectionHelper.GetMG(String computerName, PSCredential credential) in c:\Users\Administrator\Documents\WindowsPowerShell\CodePlex\smlets\Main\Source\SMLets\SMLets\Helper.cs:line 301
at SMLets.SMCmdletBase.BeginProcessing() in c:\Users\Administrator\Documents\WindowsPowerShell\CodePlex\smlets\Main\Source\SMLets\SMLets\Helper.cs:line 69

wrote Dec 21, 2014 at 3:15 PM

psikic wrote Dec 21, 2014 at 3:30 PM

After looking at the source code, I notice we have these lines:
        if ( ! ht.ContainsKey(emg.ConnectionSettings.ServerName))
        {
            ht.Add(emg.ConnectionSettings.ServerName,emg);
        }
I think SMLets was just never written to be explicitly thread-safe. I'm assuming what is happening is multiple runbooks are doing the "ContainsKey" check at the same time and then both proceeding to run the ht.Add. Sometimes one of the runbooks is able to do the Add and the other one gets this error. Sometimes both of them get the error. There could be locking added around this block of code to make the operation atomic, but there might be a better way to seperate the data structure so the multiple threads don't share it?