8000 fix race condition between ProgressRecord being updated while rendering by SteveL-MSFT · Pull Request #2771 · PowerShell/PowerShell · GitHub
[go: up one dir, main page]

Skip to content

fix race condition between ProgressRecord being updated while rendering #2771

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 44 additions & 21 deletions src/Microsoft.PowerShell.ConsoleHost/host/msh/PendingProgress.cs
7D13
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Management.Automation;
using System.Management.Automation.Host;
using System.Management.Automation.Internal;
using System.Threading;

using Dbg = System.Management.Automation.Diagnostics;

Expand Down Expand Up @@ -204,21 +205,29 @@ class PendingProgress
void
RemoveNode(ArrayList nodes, int indexToRemove)
{
_pendingProgressLock.EnterWriteLock();
try
{
#if DEBUG || ASSERTIONS_TRACE
ProgressNode nodeToRemove = (ProgressNode)nodes[indexToRemove];
ProgressNode nodeToRemove = (ProgressNode)nodes[indexToRemove];

Dbg.Assert(nodes != null, "can't remove nodes from a null list");
Dbg.Assert(indexToRemove < nodes.Count, "index is not in list");
Dbg.Assert(nodes[indexToRemove] != null, "no node at specified index");
Dbg.Assert(nodeToRemove.Children == null || nodeToRemove.Children.Count == 0, "can't remove a node with children");
Dbg.Assert(nodes != null, "can't remove nodes from a null list");
Dbg.Assert(indexToRemove < nodes.Count, "index is not in list");
Dbg.Assert(nodes[indexToRemove] != null, "no node at specified index");
Dbg.Assert(nodeToRemove.Children == null || nodeToRemove.Children.Count == 0, "can't remove a node with children");
#endif

nodes.RemoveAt(indexToRemove);
--_nodeCount;
nodes.RemoveAt(indexToRemove);
--_nodeCount;

#if DEBUG || ASSERTIONS_ON
Dbg.Assert(_nodeCount == this.CountNodes(), "We've lost track of the number of nodes in the tree");
Dbg.Assert(_nodeCount == this.CountNodes(), "We've lost track of the number of nodes in the tree");
#endif
}
finally
{
_pendingProgressLock.ExitWriteLock();
}
}


Expand Down Expand Up @@ -289,13 +298,21 @@ class PendingProgress
void
AddNode(ArrayList nodes, ProgressNode nodeToAdd)
{
nodes.Add(nodeToAdd);
++_nodeCount;
_pendingProgressLock.EnterWriteLock();
try
{
nodes.Add(nodeToAdd);
++_nodeCount;

#if DEBUG || ASSERTIONS_TRACE
Dbg.Assert(_nodeCount == this.CountNodes(), "We've lost track of the number of nodes in the tree");
Dbg.Assert(_nodeCount <= maxNodeCount, "Too many nodes in tree!");
#endif
}
finally
{
_pendingProgressLock.ExitWriteLock();
}
}


Expand Down Expand Up @@ -760,21 +777,29 @@ internal override
return;
}

foreach (ProgressNode node in nodes)
_pendingProgressLock.EnterReadLock();
try
{
int lines = strings.Count;
foreach (ProgressNode node in nodes)
{
int lines = strings.Count;

node.Render(strings, indentation, maxWidth, rawUI);
node.Render(strings, indentation, maxWidth, rawUI);

if (node.Children != null)
{
// indent only if the rendering of node actually added lines to the strings.
if (node.Children != null)
{
// indent only if the rendering of node actually added lines to the strings.

int indentationIncrement = (strings.Count > lines) ? 2 : 0;
int indentationIncrement = (strings.Count > lines) ? 2 : 0;

RenderHelper(strings, node.Children, indentation + indentationIncrement, maxWidth, rawUI);
RenderHelper(strings, node.Children, indentation + indentationIncrement, maxWidth, rawUI);
}
}
}
finally
{
_pendingProgressLock.ExitReadLock();
}
}


Expand Down Expand Up @@ -1207,8 +1232,6 @@ internal static
private ArrayList _topLevelNodes = new ArrayList();
private int _nodeCount;
private const int maxNodeCount = 128;
private ReaderWriterLockSlim _pendingProgressLock = new ReaderWriterLockSlim();
}
} // namespace



0