Skip to content
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

Add a PipelineStopToken cancellation token property to PSCmdlet #17444

Open
SeeminglyScience opened this issue May 26, 2022 · 6 comments · May be fixed by #24620
Open

Add a PipelineStopToken cancellation token property to PSCmdlet #17444

SeeminglyScience opened this issue May 26, 2022 · 6 comments · May be fixed by #24620
Labels
In-PR Indicates that a PR is out for the issue Issue-Enhancement the issue is more of a feature request than a bug KeepOpen The bot will ignore these and not auto-close WG-Engine core PowerShell engine, interpreter, and runtime

Comments

@SeeminglyScience
Copy link
Collaborator

Summary of the new feature / enhancement

A common pattern for binary cmdlets is to create a cancellation token source that is then cancelled in PSCmdlet.StopProcessing().

This is a very useful pattern to enable cancelling a method that takes CancellationToken without having to poll for completion. Having this available by default would reduce a lot of boilerplate in binary cmdlets. Boilerplate example:

namespace MyModule;

[Cmdlet(VerbsDiagnostic.Test, "MyCommand")]
public class TestMyCommand : PSCmdlet, IDisposable
{
    private readonly CancellationTokenSource _stopping = new();

    protected override void ProcessRecord()
    {
        try
        {
            Task.Delay(2000, _stopping.Token).GetAwaiter().GetResult();
        }
        catch (OperationCancelledException)
        {
            throw new PipelineStoppedException();
        }
    }

    protected override void StopProcessing() => _stopping.Cancel();

    public void Dispose() => _stopping.Dispose();
}

This pattern is not possible in PowerShell directly, instead a script must poll a task for completion if it wants to respect pipeline stops. Polling example:

$task = [System.Threading.Tasks.Task]::Delay(2000)
while (-not $task.AsyncWaitHandle.WaitOne(200)) { }
$null = $task.GetAwaiter().GetResult();

Even then all you can do is honor pipeline stops, you can't request cancellation of the work being done in another thread.

Proposed technical implementation details (optional)

namespace System.Management.Automation;

public abstract class PSCmdlet
{
+   private CancellationTokenSource? _pipelineStopTokenSource;

+   public CancellationToken PipelineStopToken => (_pipelineStopTokenSource ??= new()).Token;

    protected virtual void StopProcessing()
    {
        using (PSTransactionManager.GetEngineProtectionScope())
        {
+           _pipelineStopTokenSource?.Cancel();
        }
    }

    internal void InternalDispose(bool isDisposing)
    {
        _myInvocation = null;
        _state = null;
        _commandInfo = null;
        _context = null;
+       _pipelineStopTokenSource?.Dispose();
+       _pipelineStopTokenSource = null;
    }
}
@SeeminglyScience SeeminglyScience added Issue-Enhancement the issue is more of a feature request than a bug Needs-Triage The issue is new and needs to be triaged by a work group. WG-Engine core PowerShell engine, interpreter, and runtime labels May 26, 2022
@SeeminglyScience
Copy link
Collaborator Author

The engine WG discussed this and agrees that it would be useful. An RFC would be required as we could not unanimously agree to the proposal above.

@SeeminglyScience SeeminglyScience removed the Needs-Triage The issue is new and needs to be triaged by a work group. label Jan 24, 2023
@iSazonov
Copy link
Collaborator

iSazonov commented Jan 25, 2023

If it is for binary cmdlets only, the public CancellationToken PipelineStopToken should be not public but protected?

Copy link
Contributor

This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

@microsoft-github-policy-service microsoft-github-policy-service bot added the Resolution-No Activity Issue has had no activity for 6 months or more label Nov 15, 2023
Copy link
Contributor

This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes.

@SeeminglyScience SeeminglyScience removed the Resolution-No Activity Issue has had no activity for 6 months or more label Nov 28, 2023
@microsoft-github-policy-service microsoft-github-policy-service bot added the Resolution-No Activity Issue has had no activity for 6 months or more label May 27, 2024
Copy link
Contributor

This issue has not had any activity in 6 months, if there is no further activity in 7 days, the issue will be closed automatically.

Activity in this case refers only to comments on the issue. If the issue is closed and you are the author, you can re-open the issue using the button below. Please add more information to be considered during retriage. If you are not the author but the issue is impacting you after it has been closed, please submit a new issue with updated details and a link to this issue and the original.

@SeeminglyScience SeeminglyScience added KeepOpen The bot will ignore these and not auto-close and removed Resolution-No Activity Issue has had no activity for 6 months or more labels May 28, 2024
@jborean93 jborean93 linked a pull request Nov 26, 2024 that will close this issue
21 tasks
@microsoft-github-policy-service microsoft-github-policy-service bot added the In-PR Indicates that a PR is out for the issue label Nov 26, 2024
@jborean93
Copy link
Collaborator

RFC to hopefully move forward with this request PowerShell/PowerShell-RFC#382. I've also opened a PR showing the PoC of the proposed approach #24620.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
In-PR Indicates that a PR is out for the issue Issue-Enhancement the issue is more of a feature request than a bug KeepOpen The bot will ignore these and not auto-close WG-Engine core PowerShell engine, interpreter, and runtime
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants