dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.25k stars 4.73k forks source link

[API Proposal]: Add API to gracefully terminate process #109432

Open tmat opened 1 day ago

tmat commented 1 day ago

Background and motivation

dotnet-watch needs to be able to terminate process gracefully, i.e. give it a chance to clean up resources.

On Windows this API would call GenerateConsoleCtrlEvent, on Unix it would send SIGTERM signal. Currently this requires reimplementing both process creation and termination using P/Invokes.

API Proposal

Multiple options. One option is to add parameter to Process.Kill that indicates whether we want forced kill or "soft" termination (Ctrl+C/SIGTERM).

Process.Kill(bool entireProcessTree, bool forced = true);

ProcessStartInfo might need a bool property, say EnableConsoleControlEvents that allows Kill to send Ctrl+C.

API Usage

var process = new Process
{
    StartInfo =
    {
        EnableConsoleControlEvents = true
        // file name, arguments, output redirection, etc.
    }
};

process.Start();

process.Kill(entireProcessTree: false, forced: false);

process.WaitForExit();

Alternative Designs

Related: https://github.com/dotnet/runtime/issues/71515

Risks

No response

dotnet-policy-service[bot] commented 1 day ago

Tagging subscribers to this area: @dotnet/area-system-diagnostics-process See info in area-owners.md if you want to be subscribed.

Symbai commented 1 day ago

Process.Kill that indicates whether we want forced kill or "soft" termination

The word kill conflicts with soft. Especially when doing it gracefully the other process still has the option to say "nope". Since we already have Process.CloseMainWindow which gracefully closes a process if it has a window, for me it makes more sense to introduce a new method, something like Process.CloseConsole etc. Otherwise it gets confusing especially for beginners which method they would have to use.

karakasa commented 1 day ago

just fyi GenerateConsoleCtrlEvent cannot send events to arbitrary processes (unless within the same console or created with a certain flag).

rjgotten commented 16 hours ago

Process.Kill that indicates whether we want forced kill or "soft" termination

The word kill conflicts with soft. Especially when doing it gracefully the other process still has the option to say "nope". Since we already have Process.CloseMainWindow which gracefully closes a process if it has a window, for me it makes more sense to introduce a new method, something like Process.CloseConsole etc. Otherwise it gets confusing especially for beginners which method they would have to use.

^ This, indeed. Instead- what seems to be needed is something like a

public class Process
{
  async Task<bool> RequestTerminateAsync(CancellationToken cancellationtoken);

  // ...
}

It should be awaitable because shutting down gracefully may take a bit. Moreover, there may be time-window affordances at play for a graceful shutdown vis-a-vis a forceful one. And those might even be OS-dependent.

Which means only afterwards, you can know whether the process was actually terminated or not. (And you might have a need to continue to issue a process.Kill if it decided to 'not come quietly.')