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

Allow user code to stop a pipeline on demand / to terminate upstream cmdlets. #3821

Open
mklement0 opened this issue May 19, 2017 · 12 comments
Labels
Issue-Discussion the issue may not have a clear classification yet. The issue may generate an RFC or may be reclassif 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 WG-NeedsReview Needs a review by the labeled Working Group
Milestone

Comments

@mklement0
Copy link
Contributor

mklement0 commented May 19, 2017

The ability to stop a pipeline on demand is currently only available internally, as used by Select-Object -First <n>, for instance.

To quote from this uservoice.com issue:

It is of great value to be able to stop the pipeline if your mission is completed before the emitting cmdlet has provided all results.

In fact, the PS pipeline would gain a completely new "feature". Currently, it is a memory throttle and provides realtime feedback at the cost of performance. If stopping the pipeline was something available to users, it could also be a generic means of running cmdlets only partially.

Select-Object is a great start but you do not always know beforehand how many elements you need. So it would be beneficial to have a Stop-Pipeline cmdlet or at least a public StopUpstreamCommandsException that a script programme can throw.

A real-world example.

Also note that there are two distinct ways to "stop" a pipeline:

  • Exiting the entire pipeline instantly (effectively aborting it) - with downstream cmdlets not getting a chance to run their End blocks, as simulated by this command using break with a dummy loop to break out of:
# Produces NO output, because Sort-Object's End block never runs.
do { 
  1..10 | % { if ($_ -gt 2) { break }; $_ } | Sort-Object -Descending
 } while ($False)

Note that without the final Sort-Object -Descending pipeline stage, you would see output, because the objects are being output in the % script block as they're being received.

This quiet termination of the entire pipeline is similar to a statement-terminating error that is silenced.


  • Stopping only the upstream cmdlets (the cmdlet calls in earlier pipeline stages), as Select-Object -First <n> does, for instance, giving downstream cmdlets a chance to run their End blocks.
# Produces (2, 1), because Sort-Object's End block IS run.
1..10 | Select-Object -First 2 | Sort-Object -Descending

This scenario is about stopping further input, while still allowing remaining pipeline stages to finish their processing.

However, the fact that the upstream cmdlets do not also get to run their End blocks can be problematic, as that may be required for cleanup tasks: see #7930; PR #9900 would instead introduce a cleanup block to ensure cleanup even when stopped via StopUpstreamCommandsException.


Originally reported for:

PowerShell Core v6.0.0-beta (v6.0.0-beta.1)
@iSazonov iSazonov added WG-Engine core PowerShell engine, interpreter, and runtime Issue-Discussion the issue may not have a clear classification yet. The issue may generate an RFC or may be reclassif labels May 19, 2017
@SteveL-MSFT SteveL-MSFT added this to the 6.1.0 milestone May 19, 2017
@SteveL-MSFT SteveL-MSFT added the Issue-Enhancement the issue is more of a feature request than a bug label May 19, 2017
@dragonwolf83
Copy link

There is a good detailed blog post on how to implement this in PowerShell today: Cancelling a Pipeline. I think it would be useful to implement something like as a built-in cmdlet.

@mklement0
Copy link
Contributor Author

Thanks, @dragonwolf83; the blog post's author, Tobias Weltner, is the same person who created the linked uservoice.com issue; the blog post elicited the following @jpsnover response (dated "over 7 years ago"):

We have wanted to add pipeline stopping for quite a while and it never got raised above the bar.

That's one lofty bar! :)

@SteveL-MSFT
Copy link
Member

Things that don't necessarily align with the PowerShell Team's priorities (which is not static) can still get done if contributed by the community :)

@iSazonov
Copy link
Collaborator

We need RFC for new cmdlet and examples of how to use the cmdlet.

@mklement0 mklement0 changed the title Allow user code to stop a pipeline on demand Allow user code to stop a pipeline on demand / to terminate upstream cmdlets. Aug 13, 2017
@alx9r
Copy link

alx9r commented Jan 1, 2018

Does anyone have a working link to Tobias' blog post mentioned above? That link seems to be dead.

@TobiasPSP
Copy link
Collaborator

Here‘s some material: http://www.powertheshell.com/stop_pipeline/

@SeeminglyScience
Copy link
Collaborator

SeeminglyScience commented Jun 20, 2022

Adding Needs-Triage so WG-Engine can discuss it. This comes up surprisingly often. Typically for profile functions, but still. The lengths one has to go through to get the same behavior is pretty wild (and unsupported).

My proposal:

  namespace System.Management.Automation
  {
      public abstract class PSCmdlet
      {
+         [DoesNotReturn]
+         public void StopUpstreamCommands();
      }
  }

If added this should be tested both for binary cmdlets (this.StopUpstreamCommands()) and script cmdlets ($PSCmdlet.StopUpstreamCommands())

@vexx32
Copy link
Collaborator

vexx32 commented Jun 23, 2022

WG-Engine discussed this today (6/23/2022).

We agree that users should have access to this functionality in some way that is not exclusive to Select-Object. It came up in discussion that there may be undesirable elements of the current behaviour of Select-Object -First $x; for instance, it doesn't appear to call upstream C# cmdlets' StopProcessing() when it cancels the remainder of a pipeline.

We need more investigation on whether this behaviour would be problematic to expose as a commonly usable API, and whether we should:

  • Make changes to the existing behaviour of the pipeline's handling of StopUpstreamCommandsException, and/or:
    • Expose the same Select-Object -First $x behaviour as-is as a public API similar to the suggestions in this issue, or
    • Expose a new public API that handles the stop upstream commands request somewhat differently to the current method used for Select-Object -First $x

@SeeminglyScience
Copy link
Collaborator

I went through every command that overrides StopProcessing but does not implement IDisposable with this command:

Find-Type -Base System.Management.Automation.PSCmdlet |
    Find-Type -Not -ImplementsInterface System.IDisposable |
    Find-Member StopProcessing -Force -Declared |
    ForEach-Object {
        dnSpy.Console.exe $_.Module.Assembly.Location --md $_.MetadataToken --no-tokens |
            bat --language cs --style 'grid,numbers,snip'

        Read-Host -Prompt 'Press enter to continue'
    }

Of all of them I found only one command that is using StopProcessing for resource cleanup (Get-Counter).

I would recommend we just fix Get-Counter as pipeline terminating errors, Select-Object -First 1 and pipeline stop exceptions thrown outside of stop requests will already cause a leak here.

@rkeithhill rkeithhill removed the Needs-Triage The issue is new and needs to be triaged by a work group. label Jul 21, 2022
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.

1 similar comment
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 Resolution-No Activity Issue has had no activity for 6 months or more labels Nov 16, 2023
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.

@SeeminglyScience SeeminglyScience removed the Resolution-No Activity Issue has had no activity for 6 months or more label Nov 16, 2023
@SteveL-MSFT SteveL-MSFT added KeepOpen The bot will ignore these and not auto-close WG-NeedsReview Needs a review by the labeled Working Group labels Apr 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Discussion the issue may not have a clear classification yet. The issue may generate an RFC or may be reclassif 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 WG-NeedsReview Needs a review by the labeled Working Group
Projects
None yet
Development

No branches or pull requests

9 participants