From eaf7279d732d762e715227f17814eb04b6574a58 Mon Sep 17 00:00:00 2001 From: Dan Travison Date: Wed, 3 Jan 2018 15:44:25 -0800 Subject: [PATCH 1/2] Build: Update Restore-PSPester to include the fix for nested describe errors (#5771) Update Restore-PSPester to include PR PowerShell/psl-pester#12 that fixes PowerShell/psl-pester#11 - unhandled exceptions in before/after bypasses Pester's enddescribe logic. Update to the latest, while we are at it. --- build.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.psm1 b/build.psm1 index 0fed7d091dd..9df7a8839d3 100644 --- a/build.psm1 +++ b/build.psm1 @@ -673,7 +673,7 @@ function Restore-PSPester $Destination = ([IO.Path]::Combine((Split-Path (Get-PSOptions -DefaultToNew).Output), "Modules")) ) - Restore-GitModule -Destination $Destination -Uri 'https://github.com/PowerShell/psl-pester' -Name Pester -CommitSha 'aa243108e7da50a8cf82513b6dd649b653c70b0e' + Restore-GitModule -Destination $Destination -Uri 'https://github.com/PowerShell/psl-pester' -Name Pester -CommitSha '1f546b6aaa0893e215e940a14f57c96f56f7eff1' } function Compress-TestContent { [CmdletBinding()] From c130f35e6eacab9452ed73d457e2d15214a08c83 Mon Sep 17 00:00:00 2001 From: Dan Travison Date: Thu, 4 Jan 2018 13:08:33 -0800 Subject: [PATCH 2/2] remoting: Handle DLLImport failure of libpsrpclient (#5622) Issue #4029 exposed two problems when failing to load libpsrpclient. WSManAPIDataCommon.ctor was not identifying the binary that failed DLLImport; hindering diagnosability PrioritySendDataCollection.Clear() would throw a NullReferenceException when called from the finalizer after an error path. This change addresses both of the above: Guard against null arrays in PrioritySendDataCollection.Clear() - called from finalizer in error paths. Diagnosability: Log the DllNotFoundException in WSManAPIDataCommon ctor and also include it as the internal exception when throwing PSRemotingTransportException. --- .../remoting/fanin/PriorityCollection.cs | 44 ++++++++++++++----- .../remoting/fanin/WSManTransportManager.cs | 16 +++++-- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs b/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs index 4e2ed03a9af..552668fba40 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs @@ -46,9 +46,11 @@ internal class PrioritySendDataCollection // actual data store(s) to store priority based data and its // corresponding sync objects to provide thread safety. private SerializedDataStream[] _dataToBeSent; + // array of sync objects, one for each element in _dataToBeSent + private object[] _dataSyncObjects; + // fragmentor used to serialize & fragment objects added to this collection. private Fragmentor _fragmentor; - private object[] _syncObjects; // callbacks used if no data is available at any time. // these callbacks are used to notify when data becomes available under @@ -95,11 +97,11 @@ internal Fragmentor Fragmentor // create serialized streams using fragment size. string[] names = Enum.GetNames(typeof(DataPriorityType)); _dataToBeSent = new SerializedDataStream[names.Length]; - _syncObjects = new object[names.Length]; + _dataSyncObjects = new object[names.Length]; for (int i = 0; i < names.Length; i++) { _dataToBeSent[i] = new SerializedDataStream(_fragmentor.FragmentSize); - _syncObjects[i] = new object(); + _dataSyncObjects[i] = new object(); } } } @@ -126,7 +128,7 @@ internal void Add(RemoteDataObject data, DataPriorityType priority) // make sure the only one object is fragmented and added to the collection // at any give time. This way the order of fragment is maintained // in the SendDataCollection(s). - lock (_syncObjects[(int)priority]) + lock (_dataSyncObjects[(int)priority]) { _fragmentor.Fragment(data, _dataToBeSent[(int)priority]); } @@ -154,15 +156,33 @@ internal void Add(RemoteDataObject data) /// internal void Clear() { - Dbg.Assert(null != _dataToBeSent, "Serialized streams are not initialized"); - lock (_syncObjects[(int)DataPriorityType.PromptResponse]) + /* + NOTE: Error paths during initialization can cause _dataSyncObjects to be null + causing an unhandled exception in finalize and a process crash. + Verify arrays and dataToBeSent objects before referencing. + */ + if (null != _dataSyncObjects && null != _dataToBeSent) { - _dataToBeSent[(int)DataPriorityType.PromptResponse].Dispose(); - } + int promptResponseIndex = (int)DataPriorityType.PromptResponse; + int defaultIndex = (int)DataPriorityType.Default; - lock (_syncObjects[(int)DataPriorityType.Default]) - { - _dataToBeSent[(int)DataPriorityType.Default].Dispose(); + lock (_dataSyncObjects[promptResponseIndex]) + { + if (null != _dataToBeSent[promptResponseIndex]) + { + _dataToBeSent[promptResponseIndex].Dispose(); + _dataToBeSent[promptResponseIndex] = null; + } + } + + lock (_dataSyncObjects[defaultIndex]) + { + if (null != _dataToBeSent[defaultIndex]) + { + _dataToBeSent[defaultIndex].Dispose(); + _dataToBeSent[defaultIndex] = null; + } + } } } @@ -895,4 +915,4 @@ internal virtual void Dispose(bool isDisposing) } #endregion -} \ No newline at end of file +} diff --git a/src/System.Management.Automation/engine/remoting/fanin/WSManTransportManager.cs b/src/System.Management.Automation/engine/remoting/fanin/WSManTransportManager.cs index b5725fe3cf2..bc9c88859f8 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/WSManTransportManager.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/WSManTransportManager.cs @@ -2602,9 +2602,19 @@ internal WSManAPIDataCommon() { ErrorCode = WSManNativeApi.WSManInitialize(WSManNativeApi.WSMAN_FLAG_REQUESTED_API_VERSION_1_1, ref _handle); } - catch (DllNotFoundException) - { - throw new PSRemotingTransportException(RemotingErrorIdStrings.WSManClientDllNotAvailable); + catch (DllNotFoundException ex) + { + PSEtwLog.LogOperationalError( + PSEventId.TransportError, + PSOpcode.Open, + PSTask.None, + PSKeyword.UseAlwaysOperational, + "WSManAPIDataCommon.ctor", + "WSManInitialize", + ex.HResult.ToString(CultureInfo.InvariantCulture), + ex.Message, + ex.StackTrace); + throw new PSRemotingTransportException(RemotingErrorIdStrings.WSManClientDllNotAvailable, ex); } // input / output streams common to all connections