1

I have a destructor that needs to be called even if the program is improperly terminated in order to ensure that an external process dies.

Currently I have registered the destructor to be called by

std::atexit(killprocess);
std::at_quick_exit(killprocess);

however this means that when the program is finished but not terminated the process isn't killed. Is there some way to ensure that either killprocess or the destructor is called either at exit or when the program is finished but not terminated?

Edit: The finished but not terminated state is from visual studio that adds a wait condition at the end. I believe this means that having registered killprocess with atexit the process destructor isn't naturally called by this point in the execution

Bomaz
  • 1,871
  • 1
  • 17
  • 22
  • 2
    What do you mean by "finished but not terminated"? Do you mean the time between `main` returns and the process actually ends? – Some programmer dude Jun 14 '17 at 09:28
  • Call killprocess as the last line in main – Richard Critten Jun 14 '17 at 09:28
  • If I understand the question right [std::at_exit](http://en.cppreference.com/w/cpp/utility/program/atexit) is actually doing what you want: `Registers the function pointed to by func to be called on normal program termination (via std::exit() or returning from the main function)`. – Andre Kampling Jun 14 '17 at 09:29
  • I think that he is looking for a way to have that function called even if the current process is killed or terminated abnormally. Imagine the `main` program is named `A` and that `killprocess` kills `B`. Now if someone type `kill A` on a terminal he wants `killprocess` to be called anyway. Is that right? – Davide Spataro Jun 14 '17 at 09:33
  • 1
    On POSIX systems (like Linux and macOS) you can *capture* certain [*signals*](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html) that are used in abnormal termination. *However* some of the "abnormal terminations" could be crashes that is because of the stuff you want to clean up with `killprocess`, which could in turn mean that `killprocess` might not work. If you have a crash, just let it happen. Catch the `SIGQUIT`, `SIGTERM`, `SIGINT` and `SIGHUP` signals, and call `exit` which will call the installed exit handlers. – Some programmer dude Jun 14 '17 at 09:42
  • Install a signal handler for the signals you want to deal with (like SIGTERM) and arrange for the process to be killed (note that what actions you are allowed to perform in a signal handler is somewhat limited). – Jesper Juhl Jun 14 '17 at 09:42
  • @DavideSpataro this is correct, I added a clarifying edit on what was causing the problem in the post – Bomaz Jun 14 '17 at 09:43
  • I would suggest what @Someprogrammerdude did. Is the cleanest solution I can think about. Read more about it here: http://man7.org/linux/man-pages/man2/sigaction.2.html and https://airtower.wordpress.com/2010/06/16/catch-sigterm-exit-gracefully/ On Windows this kind of functionality is less powerful though cause windows do not provide all the signals Unix does. This is also relevant for you https://stackoverflow.com/questions/32389905/sigaction-and-porting-linux-code-to-windows – Davide Spataro Jun 14 '17 at 09:47
  • 1
    Do you mean the "Press any key..." text that Visual Studio puts in terminated console application windows? Then your program have already been *terminated* and no longer runs at all. If the program exited normally then your exit-handlers and destructors of global and static objects would have already run. This state between program being terminated and Visual Studio waiting for you to press a key is all handled by Visual Studio. – Some programmer dude Jun 14 '17 at 09:47
  • 1
    What does your destructor? Calling exit() tells the kernel (UNIX, Linux or Windows) to de-allocate alle the process memory. There needs nothing to be cleaned up, it will simply cease to exit. When you for example have to delete files on a crash then write another process which starts your app, guard it, and do your special stuff in case of a crash (abnormal programm exit). – user743414 Jun 14 '17 at 09:53
  • atexit() ensures the function is called on normal program termination. That's what it is supposed to do, and it does it well, in LIFO order. I've been using it for years. – Michaël Roy Jun 14 '17 at 10:25

2 Answers2

1

I think you are asking the wrong question. Your aim is actually to find a way to make sure that external process dies if parent process dies. But there is no way to ensure this just by relying on some function call in parent process. There is always a chance for parent process to fall into inconsistent state or otherwise inevitably fail to call this cleanup function. So there are some other mechanisms to achieve desired behavior, such as handle some kinds of keepalives in child process. For example you can supply pipe from parent process, so when it terminates for whatever reason parent process pipe end will be automatically closed by the system and child process can figure out that it needs to exit.

user7860670
  • 35,849
  • 4
  • 58
  • 84
1

Exit handler registered by std::atexit should be called on normal process end. If it is not the case, then you have to look elsewhere. See documentation for std::atexit. Maybe you want to set std::set_terminate handler too. Some program endings can't be handled, so if you want to be sure, you have to resort to some kind of external monitoring. Few ideas are already in the comments.

Marek Vitek
  • 1,573
  • 9
  • 20