You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Race condition exception when accessing $Host.UI.psobject.Properties inside a runspace #31
InvalidOperation: Cannot index into a null array.InvalidOperation: Cannot index into a null array.InvalidOperation: Cannot index into a null array.InvalidOperation: Cannot index into a null array.
Error details
PS C:\> Get-ErrorException : Type : System.Management.Automation.RuntimeException ErrorRecord : Exception : Type : System.Management.Automation.ParentContainsErrorRecordException Message : Cannot index into a null array. HResult : -2146233087 CategoryInfo : InvalidOperation: (:) [], ParentContainsErrorRecordException FullyQualifiedErrorId : NullArray InvocationInfo : ScriptLineNumber : 1 OffsetInLine : 26 HistoryId : -1 Line : 1 | Should -BeExactly 1; $supportsVT = $Host.UI.psobject.Properties['SupportsVirtualTerminal'].Value PositionMessage : At line:1 char:26 + … eExactly 1; $supportsVT = $Host.UI.psobject.Properties['SupportsVirtu … + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CommandOrigin : Internal ScriptStackTrace : at <ScriptBlock>, <No file>: line 1 TargetSite : System.Object CallSite.Target(System.Runtime.CompilerServices.Closure, System.Runtime.CompilerServices.CallSite, System.Object, System.String) Message : Cannot index into a null array. Data : System.Collections.ListDictionaryInternal Source : Anonymously Hosted DynamicMethods Assembly HResult : -2146233087 StackTrace : at CallSite.Target(Closure, CallSite, Object, String) at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1) at System.Management.Automation.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)CategoryInfo : InvalidOperation: (:) [], RuntimeExceptionFullyQualifiedErrorId : NullArrayInvocationInfo : ScriptLineNumber : 1 OffsetInLine : 26 HistoryId : -1 Line : 1 | Should -BeExactly 1; $supportsVT = $Host.UI.psobject.Properties['SupportsVirtualTerminal'].Value PositionMessage : At line:1 char:26 + … eExactly 1; $supportsVT = $Host.UI.psobject.Properties['SupportsVirtu … + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CommandOrigin : InternalScriptStackTrace : at <ScriptBlock>, <No file>: line 1
Environment data
Name Value
---------
PSVersion 7.3.6
PSEdition Core
GitCommitId 7.3.6
OS Microsoft Windows 10.0.19045
Platform Win32NT
PSCompatibleVersions {1.0,2.0,3.0,4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Version
ThreadJob 2.0.3 and Microsoft.PowerShell.ThreadJob 2.1.0
I cannot repro this in 5.1 or 7.3.6 when running in or out of WT, either when using Microsoft.PowerShell.ThreadJob v2.1.0 or ThreadJob 2.0.3 on Microsoft Windows 10.0.25905 - aka Win 11 23H2 via the Insiders Dev ring
Where can I get the 2.1.0 version, so I could test it on Windows 10 and PowerShell 5.1 and 7.3.6? On PowerShell Gallery there is only 2.0.3. The same on GitHub repo.
Install-Module Microsoft.PowerShell.ThreadJob installs the renamed and updated ThreadJob module & ThreadJob module is technically obsolete going forward as when the PowerShell team took ownership of the module it was renamed, although I think this may not have been well communicated at the time
Thanks, sorry, I've missed the info about the new module name. Will test it tomorrow. I've just finished a 9 hour car drive for the holidays so I wasn't thinking clearly.
Based on the callstack, it appears that ListDictionary is being used somewhere which is not threadsafe. In this case, this doesn't appear to be an issue with ThreadJob itself, but something the thread is accessing is not threadsafe and results in the race condition.
If the actual use case is to see within a thread if SupportsVirtualTerminal is true/false, then it would be best to capture that outside of the thread job and pass it in.
The issue was detected first when the Pester was executed with ThreadJob in order to speed up infrastructure tests. Pester is accessing the SupportsVirtualTerminal inside the Pester.psm1. I guess that Pester authors weren't aware that this is not thread safe and it would require change in Pester code.
I got lots of help from Patrick Meinecke (@SeeminglyScience), when debugging this issue. Maybe you could contact him for some more in-depth analysis.
I would agree that I don't think it's a ThreadJob problem. My guess is that it's a race condition in how PowerShell is creating the internal PSMemberInfoCollection<> and caching it in the member resurrection table.
At a glance it looks like there's a lock around the creation of the underlying collection, but the collection itself is populated lazily with no lock.
I'd also second the suggestion of working around it by accessing the object before hand in the primary thread if possible. I'm hesitant to suggest more locks there as it may have a noticeable impact on performance for an issue that doesn't get hit often.
Activity
kilasuit commentedon Jul 26, 2023
I cannot repro this in 5.1 or 7.3.6 when running in or out of WT, either when using Microsoft.PowerShell.ThreadJob v2.1.0 or ThreadJob 2.0.3 on
Microsoft Windows 10.0.25905 - aka Win 11 23H2 via the Insiders Dev ringkborowinski commentedon Jul 27, 2023
Where can I get the 2.1.0 version, so I could test it on Windows 10 and PowerShell 5.1 and 7.3.6? On PowerShell Gallery there is only 2.0.3. The same on GitHub repo.
kilasuit commentedon Jul 27, 2023
Install-Module Microsoft.PowerShell.ThreadJobinstalls the renamed and updated ThreadJob module & ThreadJob module is technically obsolete going forward as when the PowerShell team took ownership of the module it was renamed, although I think this may not have been well communicated at the timekborowinski commentedon Jul 27, 2023
Thanks, sorry, I've missed the info about the new module name. Will test it tomorrow. I've just finished a 9 hour car drive for the holidays so I wasn't thinking clearly.
kborowinski commentedon Jul 27, 2023
Ryan Yates (@kilasuit) Did test it with

Microsoft.PowerShell.ThreadJobmodule v2.1.0, still the same issue:To be sure, I have tested it on 3 different computers:
Also always try it on the new PowerShell session, do not try it in the current if there was no repro. If still no success try this example:
kilasuit commentedon Jul 28, 2023
Adding this snippet from the Discord discussion yesterday from Patrick Meinecke (@SeeminglyScience) as another way to repro this
SteveL-MSFT commentedon Aug 23, 2023
Based on the callstack, it appears that ListDictionary is being used somewhere which is not threadsafe. In this case, this doesn't appear to be an issue with ThreadJob itself, but something the thread is accessing is not threadsafe and results in the race condition.
If the actual use case is to see within a thread if
SupportsVirtualTerminalis true/false, then it would be best to capture that outside of the thread job and pass it in.kborowinski commentedon Aug 23, 2023
The issue was detected first when the Pester was executed with ThreadJob in order to speed up infrastructure tests. Pester is accessing the
SupportsVirtualTerminalinside the Pester.psm1. I guess that Pester authors weren't aware that this is not thread safe and it would require change in Pester code.I got lots of help from Patrick Meinecke (@SeeminglyScience), when debugging this issue. Maybe you could contact him for some more in-depth analysis.
SeeminglyScience commentedon Aug 23, 2023
I would agree that I don't think it's a ThreadJob problem. My guess is that it's a race condition in how PowerShell is creating the internal
PSMemberInfoCollection<>and caching it in the member resurrection table.At a glance it looks like there's a lock around the creation of the underlying collection, but the collection itself is populated lazily with no lock.
I'd also second the suggestion of working around it by accessing the object before hand in the primary thread if possible. I'm hesitant to suggest more locks there as it may have a noticeable impact on performance for an issue that doesn't get hit often.