Jump to content
Sign in to follow this  
Der schöne Günther

CTRL+C to a console app vs. TerminateProcess(..)

Recommended Posts

Posted (edited)

I have a stupid question on how to "gracefully" terminate a Windows console application.

I am not very familiar with how processes are established, how parent/child relationships are handled, consoles, all that. I might be missing basics.

 

What I am doing:

  • I have a central application with a VCL interface
  • It uses CreateProcess(..) to invisibly spawn some console applications in the background
  • Some are kept running 24/7, some are just started on demand, crunch some data, then terminate
  • These console applications get their stdIn, stdOut and stdErr pipes redirected to some pipes I created in my central applications, so I can easily process their output, and control them (if they get controlled from stdIn).
  • So far, everything worked like a breeze

 

My issue now:

  • I am now integrating another console application that just runs 24/7 and has no way of gracefully shutting it down
  • It will only end on either pressing CTRL+C on a regular terminal, or by sending it a CTRL_BREAK_EVENT from my central application by using GenerateConsoleCtrlEvent.
  • I know that Windows will "clean up" after the process has ended, but I am not sure if this way of shutting the process down is still a bit too "rude"

 

My question:

  • The documentation of the GenerateConsoleCtrlEvent function states "All console processes have a default handler function that calls the ExitProcess function."
  • The documentation on ExitProcess gets into more detail of what it actually does, but I have a hard time understanding the implications.

 

After sending the CTRL_BREAK_EVENT to the console application, my application will still give it a few hundred milliseconds to power down until it will resort to TerminateProcess but never has to, because the console application will finish within less than 5 ms.

 

I am just unsure whether I am doing it right or maybe there is a better way of "gracefully" shutting down a console application that does not handle CTRL+C at all.

Edited by Der schöne Günther

Share this post


Link to post

You nicely summarized the good, the bad and the ugly in spawning console processes.

 

My thoughts here:

1) The role of thumb for console application to be terminated at any time, and these signals or ControlEvent are not to reliable to be depends on, yet there is some cases where they are needed to not lose some job or as you named it gracefully terminate.

2) as for application you pointed to wstcp, i don't see any such event handler in the source, (may be i missed something) but you can check for your self https://rust-cli.github.io/book/in-depth/signals.html

3) As for your own processes then i suggest to try different IPC than standard console pipe, like Memory Sharing, it will give you better speed, like you can use background threads to wait on events or simply let the spawned processed write to the named shared memory passed to them in a command line and the mother process will check with intervals and read ... remember there nothing prevent a spawned from allocating shared memory too for lets say specific temporary file or stream of data and put the name in predefined table which also shared but from the owner process and passed to the child... anyway there is many approaches to handle this, and they all will remove the need the dependency on events like CTRL+C

4) if you not sure if the 3rd party process does require graceful termination then don't use TerminateProcess, make sure all your other process handle such event and either refuse to close or terminate too, but again you need to tell them first through some IPC that an event is coming and should be ignored.

 

Again for that "WebSocket to TCP proxy" it is fine to use terminate process.

 

1 hour ago, Der schöne Günther said:
  • The documentation of the GenerateConsoleCtrlEvent function states "All console processes have a default handler function that calls the ExitProcess function."
  • The documentation on ExitProcess gets into more detail of what it actually does, but I have a hard time understanding the implications.

All the concerning points in ExitProcess are for a process calling ExitProcess itself and it is recommending to switch to TerminateProcess for the case where the same process is not sure if it has a thread locking a detaching DLL callback function, so TerminateThread is safer and should be in mind when designing an application.

Also notice my suggestion above for using shared memory and wait can be the worst because of if an application is built to wait on some value in memory shared then TerminateProcess will put the waiting process in deadlock, hence you should a thread to poll the value and not wait, or wait on an event, created by the child process hence the Exit/Terminate will signal it.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×