-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
[API Proposal]: Non-cooperative abortion of code execution #69622
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Because this API can unpredictably corrupt the application's state by design and to avoid misuse, it might need to be gated by an opt-in runtime configuration setting. This means we also need a My understanding is that it's impossible to implement this API safely, and this would strongly discourage using it as a replacement of |
whats the differnce of this vs a method that takes a cancellation token? |
A method with a cancellation token has to periodically check for it and pass it down the call stack. This API will allow terminating methods forcefully and immediately, even if they don't accept a cancellation token. |
This is a dangerous API, one very few folks should use, but I don't see how the suggestion helps; it just forces extra boilerplate that someone who needs to call this has to go through, and is on the path towards reintroducing Code Access Security. How are the dangers here different from a library, say, P/Invoking to TerminateThread and similarly leaving things in a corrupted state? That doesn't require additional opt-in today. Opting-in is the act of calling the method or using a library that does. |
This API is marked ready for review. Before we approve it, I'd like to get confirmation from the runtime + libraries architects that we're not committing to changing any BCL code to be resilient in the face of asynchronous exceptions being thrown. The original post from Don Syme said that the reliability for this API has to be "good but not perfect" - but I never saw a definition of how we would measure success here. I really don't want this to be a pretext for reintroducing CERs back into our code after we spent so much effort removing them. See dotnet/docs#29624 (comment) for some additional discussion on how newer coding constructs (like the array pool) could result in additional pits of failure with regard to asynchronous exceptions. |
We're not going to add back CERs. As far as library code is concerned, thread aborts do not exist. |
I wonder if it could be useful to expose a "was aborted?" API from this to let the original caller know if an interrupt indeed took place. They could check exceptions coming from the In the extreme, the caller might want the answers to the following questions:
|
Is it different from the |
My understanding is that ControlledExecution cex;
try
{
cex.Run(some_action);
}
catch (Exception ex) when (cex.WasCanceled)
{
throw new OperationCanceledException(); // normalize
} |
Ah ok, so this would be just for convenience. I am not sure whether it is worth it. The interactive window is going to have wrapper around this that can keep track of what is going on. |
Sure. So the suggestion is that since the code which kicks off the work and the code which aborts the work are assumed to have been written by the same author, they should already have some synchronization mechanism between themselves to communicate this information? I'm fine with that. |
Maybe the |
How about marking this class |
@deeprobin it won't work, we need #31354. And it wouldn't solve the problem of a dependency using it. The goal of my proposal is to entirely disable it from any library in the app, like the |
namespace System.Runtime;
[Obsolete(some diag code)]
public static class ControlledExecution
{
public static void Run(Action action, CancellationToken cancellationToken);
} |
Implemented in #71661. |
Background and motivation
Update: Replaced
TryThrowException
withTryAbort
as was in the original proposal.There is a number of execution environments for .NET code that may benefit from having an option to perform non-cooperative abortion of code execution, e.g., C# and F# interactive compilers (
csi
andfsi
) or .NET Interactive Notebooks (see #41291). While the legacy Framework provided theThread.Abort
method, it has never been supported by .NET Core, because aborting code execution at a random point is inherently unsafe and may leave the process in an inconsistent or a corrupted state. Thus, the only available option to interrupt stuck code execution is to terminate the process and lose its state, which is undesirable for interactive scenarios.Below is the proposed API to allow controlled execution of given code. The
Run
method starts execution of the delegate andTryAbort
method may be used to attempt aborting its execution by throwing an asynchronousThreadAbortException
on that thread. Aborting may be successful only when the code is executing managed code, e.g., running a CPU-intensive loop, on the original thread. This API would not help cases where the thread is stuck in unmanaged code or waiting for some other thread to finish its work.The implementation will generally use the same mechanism as the one utilized by the debugger to abort threads doing function evaluation (
Thread::UserAbort
). That includes marking the thread for abortion, suspending it, checking whether it is running managed code and safe to redirect, redirecting the thread to theThrowControlForThread
runtime helper, walking the stack to verify the tread is in a safe spot, and raising the exception for thread abort.A possible option to make the implementation simpler is to rely only on GC polls / polls for thread abort instead of redirecting the thread on Windows, similarly to what is done on Unixes.
This design was discussed in #66480.
API Proposal
API Usage
Alternative Designs
No response
Risks
No response
The text was updated successfully, but these errors were encountered: