Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ graceful shutdown best practices

I'm writing a multi-threaded c++ application for *nix operating systems. What are some best practices for terminating such an application gracefully? My instinct is that I'd want to install a signal handler on SIGINT (SIGTERM?) which stops/joins my threads. Also, is it possible to "guarantee" that all destructors are called (provided no other errors or exceptions are thrown while handling the signal)?

like image 847
fredbaba Avatar asked Dec 28 '13 22:12

fredbaba


People also ask

Why graceful shutdown is important?

Graceful shutdown means that the OS (operating system) can safely shut down its processes and close all connections, however long that takes. This helps to prevent accidental data loss or other unexpected problems if the shutdown is performed intentionally by the user.


2 Answers

Some considerations come to mind:

  • designate 1 thread to be responsible for orchestrating the shutdown, eg, as Dithermaster suggested, this could be the main thread if you are writing a standalone application. Or if you are writing a library, provide an interface (eg function call) whereby a client program can terminate the objects created within the library.

  • you cannot guarantee destructors are called; that is up to you, and requires carefully calling delete for each new. Maybe smart pointers will help you. But, really, this is a design consideration. The major components should have start & stop semantics, which you could choose to invoke from the class constructor & destructor.

  • the shutdown sequence for a set of interacting objects is something that can require some effort to get correct. E.g., before you delete an object, are you sure some timer mechanism is not going to try calling it in few micro/milli/seconds later? Trial and error is your friend here; develop a framework which can repeatedly & rapidly start and stop your application to tease out shutdown related race-conditions.

  • signals are one way to trigger an event; others might be periodically polling for a known file, or opening a socket and receiving some data on it. Either way, you want to decouple the shutdown sequence code from the trigger event.

like image 166
Darren Smith Avatar answered Sep 18 '22 19:09

Darren Smith


My recommendation is that the main thread shut down all worker threads before exiting itself. Send each worker an event telling it to clean up and exit, and wait for each one to do so. This will allow all C++ destructors to run.

like image 35
Dithermaster Avatar answered Sep 17 '22 19:09

Dithermaster