From 35aaecf31d962efd42e84aca65ad5f0d3f2b76e9 Mon Sep 17 00:00:00 2001 From: Sergey Zalyadeev Date: Thu, 30 Dec 2021 22:17:14 +0300 Subject: [PATCH 1/3] fix crash Copy-Item to remote session (#16542) --- .../remoting/fanin/PriorityCollection.cs | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs b/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs index 7baebdc98ae..5260e42bad9 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs @@ -220,22 +220,42 @@ internal byte[] ReadOrRegisterCallback(OnDataAvailableCallback callback, lock (_readSyncObject) { priorityType = DataPriorityType.Default; - - // send data from which ever stream that has data directly. byte[] result = null; - result = _dataToBeSent[(int)DataPriorityType.PromptResponse].ReadOrRegisterCallback(_onSendCollectionDataAvailable); - priorityType = DataPriorityType.PromptResponse; - if (result == null) - { - result = _dataToBeSent[(int)DataPriorityType.Default].ReadOrRegisterCallback(_onSendCollectionDataAvailable); - priorityType = DataPriorityType.Default; - } - // no data to return..so register the callback. - if (result == null) + if (_dataSyncObjects != null && _dataToBeSent != null) { - // register callback. - _onDataAvailableCallback = callback; + const int promptResponseIndex = (int)DataPriorityType.PromptResponse; + + lock (_dataSyncObjects[promptResponseIndex]) + { + //NOTE: fix unhandled NullReference exception; + //_dataToBeSent[promptResponseIndex] is disposed by Clear method from different thread + if (_dataToBeSent[promptResponseIndex] != null) + { + // send data from which ever stream that has data directly. + result = _dataToBeSent[promptResponseIndex].ReadOrRegisterCallback(_onSendCollectionDataAvailable); + priorityType = DataPriorityType.PromptResponse; + } + } + + if (result == null) + { + const int defaultIndex = (int)DataPriorityType.Default; + lock (_dataSyncObjects[defaultIndex]) + { + if (_dataToBeSent[defaultIndex] != null) + { + result = _dataToBeSent[defaultIndex].ReadOrRegisterCallback(_onSendCollectionDataAvailable); + priorityType = DataPriorityType.Default; + } + } + } + // no data to return..so register the callback. + if (result == null) + { + // register callback. + _onDataAvailableCallback = callback; + } } return result; From 6b6a69b25a2e629b2da15bb56f3628a2c628cd0d Mon Sep 17 00:00:00 2001 From: Sergey Zalyadeev Date: Tue, 11 Jan 2022 23:02:46 +0300 Subject: [PATCH 2/3] update comments --- .../engine/remoting/fanin/PriorityCollection.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs b/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs index 5260e42bad9..2e8fa948b65 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs @@ -225,11 +225,9 @@ internal byte[] ReadOrRegisterCallback(OnDataAvailableCallback callback, if (_dataSyncObjects != null && _dataToBeSent != null) { const int promptResponseIndex = (int)DataPriorityType.PromptResponse; - lock (_dataSyncObjects[promptResponseIndex]) { - //NOTE: fix unhandled NullReference exception; - //_dataToBeSent[promptResponseIndex] is disposed by Clear method from different thread + // _dataToBeSent array items can be asynchronously disposed and set to null value. if (_dataToBeSent[promptResponseIndex] != null) { // send data from which ever stream that has data directly. @@ -243,6 +241,7 @@ internal byte[] ReadOrRegisterCallback(OnDataAvailableCallback callback, const int defaultIndex = (int)DataPriorityType.Default; lock (_dataSyncObjects[defaultIndex]) { + // _dataToBeSent array items can be asynchronously disposed and set to null value. if (_dataToBeSent[defaultIndex] != null) { result = _dataToBeSent[defaultIndex].ReadOrRegisterCallback(_onSendCollectionDataAvailable); @@ -250,6 +249,7 @@ internal byte[] ReadOrRegisterCallback(OnDataAvailableCallback callback, } } } + // no data to return..so register the callback. if (result == null) { From bb6be3865ad9a1892388bb5e47aa1bfdc31232a3 Mon Sep 17 00:00:00 2001 From: Sergey Zalyadeev Date: Thu, 13 Jan 2022 13:31:38 +0300 Subject: [PATCH 3/3] remove lock (#16542) --- .../remoting/fanin/PriorityCollection.cs | 48 +++++++------------ 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs b/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs index 2e8fa948b65..a29a202b5ae 100644 --- a/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs +++ b/src/System.Management.Automation/engine/remoting/fanin/PriorityCollection.cs @@ -220,42 +220,30 @@ internal byte[] ReadOrRegisterCallback(OnDataAvailableCallback callback, lock (_readSyncObject) { priorityType = DataPriorityType.Default; + // Send data from which ever stream that has data directly. byte[] result = null; + SerializedDataStream promptDataToBeSent = _dataToBeSent[(int)DataPriorityType.PromptResponse]; + if (promptDataToBeSent is not null) + { + result = promptDataToBeSent.ReadOrRegisterCallback(_onSendCollectionDataAvailable); + priorityType = DataPriorityType.PromptResponse; + } - if (_dataSyncObjects != null && _dataToBeSent != null) + if (result == null) { - const int promptResponseIndex = (int)DataPriorityType.PromptResponse; - lock (_dataSyncObjects[promptResponseIndex]) + SerializedDataStream defaultDataToBeSent = _dataToBeSent[(int)DataPriorityType.Default]; + if (defaultDataToBeSent is not null) { - // _dataToBeSent array items can be asynchronously disposed and set to null value. - if (_dataToBeSent[promptResponseIndex] != null) - { - // send data from which ever stream that has data directly. - result = _dataToBeSent[promptResponseIndex].ReadOrRegisterCallback(_onSendCollectionDataAvailable); - priorityType = DataPriorityType.PromptResponse; - } - } - - if (result == null) - { - const int defaultIndex = (int)DataPriorityType.Default; - lock (_dataSyncObjects[defaultIndex]) - { - // _dataToBeSent array items can be asynchronously disposed and set to null value. - if (_dataToBeSent[defaultIndex] != null) - { - result = _dataToBeSent[defaultIndex].ReadOrRegisterCallback(_onSendCollectionDataAvailable); - priorityType = DataPriorityType.Default; - } - } + result = defaultDataToBeSent.ReadOrRegisterCallback(_onSendCollectionDataAvailable); + priorityType = DataPriorityType.Default; } + } - // no data to return..so register the callback. - if (result == null) - { - // register callback. - _onDataAvailableCallback = callback; - } + // No data to return..so register the callback. + if (result == null) + { + // Register callback. + _onDataAvailableCallback = callback; } return result;