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
Implement Cleanup { } Function Block #9900
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImplicitRemotingCommands.cs
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImplicitRemotingCommands.cs
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImplicitRemotingCommands.cs
Show resolved
Hide resolved
5e23ce9
to
8dd86bb
Compare
src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImplicitRemotingCommands.cs
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImplicitRemotingCommands.cs
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImplicitRemotingCommands.cs
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Utility/commands/utility/ImplicitRemotingCommands.cs
Show resolved
Hide resolved
680c351
to
330a48e
Compare
As this is a change to the core language it should go through the RFC process. |
@BrucePay please see PowerShell/PowerShell-RFC#207 😄 |
This is not meant to be an automatic thing to release resources. The code must still be written to do so. But if such code cannot be guaranteed to be run without users accidentally cancelling it out of impatience, there isn't much point in writing it, is there? |
I don't agree with this. As I mentioned above, the very first time I heard about an ask for this, is to have a finally-like thing that covers all When it comes to Ctrl+c and the interactive scenario, the question is "does the difference between 'guaranteed' and 'best-effort' really matters practically". After all, the As you brought up, after suspending a stopping pipeline, the For now, I will put aside the discussion about how |
What's worse than what's happening now could happen? :-))) You are ignoring the fact that this is a shell and it should behave like a shell as indicated above by @JamesWTruher. For some reason, you think PowerShell users are much more stupid than script writers. Aren't they more often than not the same people? :-) And won't there be a lot of modules in which this block will be used incorrectly and work so badly that it should be interrupted? Again, there is no guarantee that resources will be freed, even in C#. The situation is even worse in PowerShell. In fact, this has not been a tragedy for many years. The formulated problem looks rather contrived. |
I am really +1 to both @vexx32 and @SeeminglyScience points here in that The main argument I can see here for being able to interrupt this with ctrl+c is that PowerShell is a shell and that everything should be cancel-able. Why is this argument being applied to a script function and not to binary cmdlets. Using the example in #9900 (comment) we can see that binary modules just plain ignore ctrl+c normally. Add-Type -OutputAssembly MyModule.dll -TypeDefinition @'
using System;
using System.Management.Automation;
using System.Threading;
namespace MyModule
{
[Cmdlet("Test" , "Cmdlet")]
public class TestCmdletCommand : PSCmdlet
{
protected override void EndProcessing()
{
try
{
Console.WriteLine("press ctrl + c");
Thread.Sleep(5000);
Console.WriteLine("end try");
}
finally {
Console.WriteLine("press ctrl + c again");
Thread.Sleep(5000);
Console.WriteLine("end finally");
}
}
}
}
'@
$module = 'MyModule'
$manifestSplat = @{
Path = 'MyModule.psd1'
NestedModules = @('MyModule.dll')
FunctionsToExport = @('Test-Cmdlet')
}
New-ModuleManifest @manifestSplat
Import-Module .\MyModule.psd1
Test-Cmdlet If the argument is that people who are writing binary modules should know what they are doing and thus not create situations where this occurs then I feel you are wrong. I've seen varying qualities in both PowerShell scripts and compiled code, just because something is written in C# doesn't mean it's better quality code. What about running a process that hooks into ctrl+c and completely ignores the signal that is sent to it causing the shell to hang anyway. Removing this functionality due to the risk of poor programming just seems wrong and is hampering good functionality without addressing the problem at hand. One of the reasons why I avoid binary cmdlets is because I dislike having to deal with compiling code, shipping multiple dlls, being harder to debug as easily, and not not being able to unload an assembly. Script functions are so much simpler to write and definitely has a lower barrier for entry. By having this feature you are in fact making it possible to write better script functions now that they can cleanup resources they open in some of the more exceptional cases. Ultimately this is a really nice feature to have and if the powers that be wish to make it interruptible I would be disappointed but still excited to be able to use the |
Thanks for your input @jborean93! Sorry for making this a bit long; it's hard to keep things short when it feels like there are multiple ongoing conversations at once, but I have tried to keep each bit as brief as I could manage. I think to some degree the conversation here really boils down to this point:
And there isn't really one answer, there's a few.
The other point being discussed here is concerns around letting folks run non-interruptible code. Most of the counterpoints here make it sound like a non-interruptible section of code is an exceptional case. At least in my experience using PowerShell, it's really not unusual at all. Ctrl+C is never as responsive as we'd all like, I'm sure. For me this really boils down to two points:
If
(emphasis is mine) That's precisely why I wrote the code this way and spent all the effort making it a bit easier to handle from PowerShell. As you say, the situation in PowerShell for properly cleaning up resources or state, is quite a bit worse than C# at the moment. This provides an avenue to rectifying that disparity. Whether or not you think it's a problem largely depends on the kinds of code you interact with on a daily basis. Perhaps our spheres of operation are a bit far apart here, but I tend to end up moving to C# because PowerShell simply doesn't provide what I'm looking for these days. |
I don't have much to add beyond strongly echoing @vexx32 here. This is a feature that makes dealing with things that require deterministic cleanup in PowerShell significantly easier than it is currently. Making it interruptible greatly limits the utility of the feature, to the point that I'm not sure I can think of a case where we'd actually employ it. It would become one more PowerShell feature that would require a nuanced explanation to people who are unfamiliar with PowerShell's numerous idiosyncrasies. The cognitive load of all these gotchas is such that it is extraordinarily difficult to teach anyone, from an experienced .NET developer to a sysadmin dabbling in some scripting, how to do anything in a robust and reliable way in PowerShell. All these efforts to make bad code (e.g. a cleanup block that did some huge amount of work and would block an interactive shell for a meaningful amount of time) have fewer negative consequences end up making it fantastically difficult to write good code. It's far easier to explain "ctrl+c doesn't interrupt cleanup, so be careful about what you do there" to someone than it is to explain that "you shouldn't use cleanup unless your scenario is one where interrupting cleanup may be OK, consider the implications of that at any point in your whole function". |
This comment has been minimized.
This comment has been minimized.
I now have the prototype for an alternative design available at #15177. It's been rebased to the master, with all existing tests passed. The major change is around 2 aspects:
The prototype doesn't do anything about Ctrl+c handling, since we don't yet have an agreement there. I haven't gone through all needed changes in steppable pipeline yet. We will need the committee's review on the error handling proposal, and if it is accepted, the next step will be writing a lot tests for the error handling. Also, we will need the committee's review on Ctrl+c handling as well. |
This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days. |
This pull request has been automatically marked as Review Needed because it has been there has not been any activity for 7 days. |
PR Summary
Adds a new
cleanup
keyword and named block for both script commands and advanced functions.RFC: PowerShell/PowerShell-RFC#207
Changes
cleanup {}
function block, including all necessary AST changes toScriptBlockAst
, new token type, tokenizer changes, etc.Dispose()
implementation (including the newcleanup {}
block type) immediately afterend {}
/EndProcessing()
is called, so as to dispose of function resources as soon as a function's task in the pipeline is complete.Dispose()
method in theCommandProcessorBase
to call theDispose()
methods for script cmdlets and functions as well.IDisposable
implementation to call thecleanup {}
script block during that code path for script cmdlets. Simple functions (utilisingDlrScriptCommandProcessor
) already inherit theDispose()
implementation fromCommandProcessorBase
so a method was added to handle their disposal by calling theircleanup{}
blocks.Cleanup { } behaviour
cleanup {}
step will skip the remainder of that Cleanup block but will not prevent subsequent cmdlets' ownCleanup {}
steps from being invoked, nor interrupt any disposal of the overall pipeline.PR Context
For functions and script cmdlets that utilise pipeline input, there is currently no possible way to reliably utilise a resource that should be timely disposed. Resources can be disposed by the pipeline, but typically this does not occur until the completion of all commands in the pipeline.
For scripts and modules that interact with external resources, this can still become problematic. This PR attempts to address this gap and bring script cmdlets closer to parity with compiled cmdlets, which are perfectly capable of simply implementing
IDisposable
and taking necessary actions there.Fix #6673
EditorSyntax PR: PowerShell/EditorSyntax#186
Open / Complicated Questions
cleanup{}
and another function block (i.e., a terminating error is thrown duringbegin
,process
, orend
, and whencleanup
is invoked, it also throws a terminating error).cleanup
(this is the same as what would happen in C# if you throw both fromtry
andfinally
, from what I can tell, in that you can only catch / see the error from thefinally
), but both errors still surface in$error
.Additional Asks
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.