-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Adding Lock statements to ProgressPane Hide and Show functions. #17498
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
Conversation
a9fa194
to
7e98bfe
Compare
This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days. |
@anmenaga @daxian-dbw @PaulHigin Can this be reviewed please? FYI - I received the following in VSCode debugging a script that was using a lot of progress bars in the PS Integrated Terminal.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other than the 1 suggestion, the change looks fine to me
@@ -26,7 +26,8 @@ class ProgressPane | |||
internal | |||
ProgressPane(ConsoleHostUserInterface ui) | |||
{ | |||
if (ui == null) throw new ArgumentNullException(nameof(ui)); | |||
if (ui == null) | |||
throw new ArgumentNullException(nameof(ui)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't tell in this editor if it lines up right, but please add braces
throw new ArgumentNullException(nameof(ui)); | |
{ | |
throw new ArgumentNullException(nameof(ui)); | |
} |
@SteveL-MSFT In what cases would |
My doubts are there are already locks in some code paths and we can fall in dead lock. I'd want understand what is a code path for the PR issue which bypasses existing locks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know this code very well, but I am uncomfortable placing large sections of code within lock statements. My concern is causing a regression where existing scripts start dead locking.
If the goal is to protect internal state (_savedRegion, _progressRegion), then I feel the fix should focus more narrowly on that.
I believe these locks are a pretty safe addition. The state of the class is fully internal, the locks could only be deadlocked if something outside of the class managed to get a lock on the lock object, but the lock object is private so that isn't possible. Sprinkling more smaller locking objects around just the internal state objects would increase the risk of mistakes and make it harder to maintain going forward. The objective is to only allow the one of the hide and show methods to be called at any one time. The only way to get a deadlock from the added locks would be for one of the show/hide methods to call the other from inside the locked code block, which isn't happening and should be easy to spot in the future should further changes be made to these methods. This was the simplest fix to an issue my team and I feel is pretty critical, clearly the ideal fix would be dig through the call tree and find where there is actually an issues with multiple threads interacting with the progress bars. but given the very specific scenario where I encountered this, it would be very complex to debug and find the true root cause. |
I have the similar concern as @PaulHigin and @iSazonov. By looking at the code, it seems the issue would happen only if more than one threads are calling The part that I don't understand is why there are multiple threads manipulating the same progress pane, and that feels to me is the root cause of this issue. |
My understanding always was that ConsoleHost is owner. And it has already has locks to exclude race conditions. But the issue shows there is a code path which bypasses these locks. |
I'm happy to update this PR with suggestions for a more appropriate fix, but I'll need pointing at the right place as I'm not familiar with the architecture of the project. |
You could look locks which works for local scenario. There are two places with such locks if I remember right. Then it would be great to find where the code is called in remoting code. There is a deserialization for ProgressRecord - a root of the issue there. |
The PowerShell/src/System.Management.Automation/engine/remoting/common/WireDataFormat/RemoteHost.cs Line 136 in b780a34
PowerShell/src/System.Management.Automation/engine/remoting/host/RemoteHostMethodInfo.cs Line 136 in b780a34
The client normally marshals the remote host write onto the pipeline thread, and we should find out why that isn't happening in this case. PowerShell/src/System.Management.Automation/engine/remoting/client/ClientMethodExecutor.cs Line 71 in b780a34
|
This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days. |
Looking at the original issue (#17497), I see that this only occurs during a WinRM remoting disconnect/reconnect event. It appears that after reconnection, the remote host calls are no longer marshaled onto the client cmdlet thread. I would like to first understand why this is happening before adding locks. My guess is some client state information is lost after the reconnect. |
This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days. |
711e347
to
2e2426d
Compare
This PR has Quantification details
Why proper sizing of changes matters
Optimal pull request sizes drive a better predictable PR flow as they strike a
What can I do to optimize my changes
How to interpret the change counts in git diff output
Was this comment helpful? 👍 :ok_hand: :thumbsdown: (Email) |
Hello All, @TravisEz13 @adityapatwardhan Reawakening this one as I've just run headlong into it again on a newer version of PowerShell. I've rebased the original commit on master. To make a point on some of the comments, it seems the feeling is that there is some issue further up the chain relative to the locks I've put in. I would argue that where I have put the locks in should have had them anyway. Whatever other issues exist, fundamentally there is a concurrent access issue in the ProgressPane class, and these changes fix that. If that means another bug becomes an non issue then isn't that win win? I have had a go at trying to find the higher level issue but have found that I'm putting much more wide sweeping changes in to deal with it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe there must be at least two threads and most likely with remote sessions to reproduce the problem (one ends its progress bar, second continues its progress bar). In this case this fix is not completely correct.
This pull request has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 15 days. It will be closed if no further activity occurs within 10 days of this comment. |
PR Summary
Following the issue #17497 locks are being added to the Hide and Show methods in ProgressPane.cs to ensure that
_savedRegion
is not set to null after being check in theIsShowing
property and being used in for loop in the Hide Method.I am not sure if this is considered an acceptable fix for this issue, there might be a higher level that this would be better fixed at, but I'm not familiar enough with the code to know where that might be.
PR Context
See Issue #17497
PR Checklist
.h
,.cpp
,.cs
,.ps1
and.psm1
files have the correct copyright headerWIP:
or[ WIP ]
to the beginning of the title (theWIP
bot will keep its status check atPending
while the prefix is present) and remove the prefix when the PR is ready.