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

Support for process restart #26

Closed
Wintereise opened this issue Jul 10, 2018 · 2 comments
Closed

Support for process restart #26

Wintereise opened this issue Jul 10, 2018 · 2 comments

Comments

@Wintereise
Copy link

Hi,

Is there any graceful way to restart a process that has for example been interrupted with Command.Kill (or by outside circumstances)?

Currently we're setting DisposeOnExit to false, and calling Command.Process.Start again. This works, but stdout/stderror redirection no longer works.

My question is, is there a better way, or is there a way to re-attach the output buffering internals if our Process.Start() hack is the recommended way forward?

@madelson
Copy link
Owner

Hi @Wintereise . While I suppose you can technically "re-start" a .NET process object by calling Start again it feels strange to me to do that since you are really just starting a completely new process. Calling Start again will blow away the std IO streams (as you are seeing) and could do weird things with subscribed events which makes code that uses this pattern prone to bugs.

MedallionShell takes the approach that processes are one-time events (Commands), e. g. associating each process with a Task which is not restartable.

Therefore, I think the best way to represent a process that may die with or without MedallionShell is to create an entirely new Command/Process object on each restart.

For example, if you want a process that auto-restarts on unexpected failure you could do something like this:

while (true)
{
    var command = ConfigureAndRunCommand(...)
         .RedirectTo(...);
    if ((await command.Task).Success) { break; }
}

In this case, we're taking advantage of a MedallionShell feature which makes sure all output has been written from redirection before allowing the Commands Task to finish. This makes sure that we won't hit thread-safety issues if the old and new process were being redirected to the same place.

If we want the ability to kill this loop ourselves, we can easily pass in a CancellationToken to Run using options.CancellationToken(...). That way, when cancellation is triggered it will (a) kill the process and (b) have the Command's task flip to the Canceled state, which will cause an OperationCanceledException to be thrown, exiting the loop.

@Wintereise
Copy link
Author

Hi @madelson

Thank you for the insight, understood.

I'll close this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants