Skip to content

Fix debugging with PSES pipeline thread changes #1574

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

Merged

Conversation

rjmholt
Copy link
Contributor

@rjmholt rjmholt commented Sep 14, 2021

This PR moves the host REPL implementation off of its own thread and back into the host itself for a synchronous implementation. This makes the host more monolithic, but because of the required coupling of the internals of the host this is pretty hard to avoid (and trying to avoid it introduces other complexity). There's still some complexity here, both because the design itself is pretty big and hard to juggle, but also because some interfaces are deliberately separated out to try and not expose the host to everything.

With the REPL integrated back in, hooking up the debugger is simpler and is now done.

Comment on lines 122 to 123
// Ensure the debugger mode is set correctly
_debugContext.EnableDebugMode();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is required for remote debugging to work

@@ -44,7 +46,7 @@ internal class BreakpointService

public async Task<List<Breakpoint>> GetBreakpointsAsync()
{
if (BreakpointApiUtils.SupportsBreakpointApis)
if (_editorServicesHost.CurrentRunspace.PowerShellVersionDetails.Version >= s_minimumBreakpointApiVersion)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not entirely sure if this logic is correct -- ideally it should depend on the client not the remote. I'll need to try out the old logic and see if that works before we merge

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BreakpointApiUtils.SupportsBreakpointApis should eventually be fixed to answer this question correctly.

else if (
e.ChangeAction == RunspaceChangeAction.Exit && false)
// _powerShellContextService.IsDebuggerStopped)
switch (e.ChangeAction)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a style change

}
}

private void PowerShellContext_DebuggerResumed(object sender, DebuggerResumeAction e)
private void PowerShellContext_DebuggerResuming(object sender, DebuggerResumingEventArgs e)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably rename this method

@@ -408,7 +408,7 @@ public async Task<string> SetVariableAsync(int variableContainerReferenceId, str
// Evaluate the expression to get back a PowerShell object from the expression string.
// This may throw, in which case the exception is propagated to the caller
PSCommand evaluateExpressionCommand = new PSCommand().AddScript(value);
object expressionResult = (await _executionService.ExecutePSCommandAsync<object>(evaluateExpressionCommand, new PowerShellExecutionOptions(), CancellationToken.None)).FirstOrDefault();
object expressionResult = (await _executionService.ExecutePSCommandAsync<object>(evaluateExpressionCommand, CancellationToken.None)).FirstOrDefault();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a ConfigureAwait(false)

}

/*
private void PopOrReinitializeRunspace()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote this as a sort of last ditch attempt to stop the extension from falling over when everything goes wrong. The code currently isn't compatible with the new implementation, so we should review it and decide whether it's worth keeping in any way or should just be gotten rid of

/// This behavior is unlikely to change and ensuring its correctness at our layer is likely to be costly.
/// See https://stackoverflow.com/q/26472251.
/// </remarks>
internal class BlockingConcurrentDeque<T>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see where this is used anywhere in this PR.
Also, should this not have a Dispose() method to clean up collections, event objects?
It is not clear to me what this is for, it would be nice to have comments illustrating its use.

Copy link
Contributor Author

@rjmholt rjmholt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to add copyright headers

@SeeminglyScience
Copy link
Collaborator

Looking great!

I did an initial run of feedback. It's mostly just a few missing ConfigureAwait's but it may be best to just ignore those here and hit it with an analyzer later.

Hopefully the "suggestions" work, haven't tried to add them from the VSCode PR extension yet.

I'll also need to spend some time with the build and see how it all feels, but I'm loving the changes and it all looks very well done. Great work Rob!

Copy link
Collaborator

@SeeminglyScience SeeminglyScience left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, it didn't submit the review with the comment. 🤷

public SecureString ReadSecureLine() => ReadSecureLineAsync(CancellationToken.None).GetAwaiter().GetResult();
public string ReadLine(CancellationToken cancellationToken)
{
return _psesHost.InvokeDelegate<string>(representation: "ReadLine", new ExecutionOptions { MustRunInForeground = true }, InvokePSReadLine, cancellationToken);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider making the delegate creation here static (assuming we can pass state in one of these parameters).

e.g.

static (@this, ct) => @this.InvokeReadLine(ct)

@andyleejordan
Copy link
Member

I did an initial run of feedback. It's mostly just a few missing ConfigureAwait's but it may be best to just ignore those here and hit it with an analyzer later.

FYI the analyzer is enabled so if this is somewhat up to date with master them missing should cause a compiler failure.

@rjmholt
Copy link
Contributor Author

rjmholt commented Oct 11, 2021

I'm going to merge this in now so we can continue work on the main branch, breaking out smaller work items into new PRs.

You can see the changes I've made to address comments in individual commits, which will be preserved in the work branch by a merge commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants