
Sometimes we need to return something to the system when we finish a program, but it may be that the user killed the process before the end of it without being expected.
It happens a lot in programs that have a loop while with tasks to be executed to the expected end!
Suppose you have this code that issues a warning at the beginning of the program and after 5 seconds the program ends and issues another warning:
#include <iostream>
#include <memory>
#include <chrono>
#include <thread>
void msgOut(){
std::cout << "The 5 second count has finished." << '\n';
}
class CountTime {
void m_start_count(){
std::this_thread::sleep_for(std::chrono::seconds(5));
}
public:
CountTime(){
std::cout << "The 5 second countdown has started!" << '\n';
this->m_start_count();
}
~CountTime(){
msgOut();
}
};
int main(){
auto ct = std::make_unique<CountTime>();
return 0;
}After compiling and running, after 5 seconds these two messages appeared in the output:
The 5 second countdown has started!
The 5 second count has ended.Now suppose that before the end of 5 seconds, you press Ctrl + c, the second message will not appear and the output will be like this:
The 5 second countdown has started!
^CIn other words, if your program has a function to be executed whenever the program ends, then it will generate a silent bug.
To solve this, we can map the signal sent and execute a certain task even if the program is interrupted before its normally expected end.
std::signalFirst let’s include the header:
#include <csignal>Create a callback function that will handle the signal, outside the execution of our class:
void signal_handler(int signal) {
if (signal == SIGINT) {
msgOut();
std::exit(EXIT_SUCCESS);
}
}And start it in the constructor, or before the start of a supposed loop that we will execute!
std::signal(SIGINT, signal_handler);The final code will be:
#include <iostream>
#include <memory>
#include <chrono>
#include <thread>
#include <csignal> // include
void msgOut(){
std::cout << "The 5 second count has finished." << '\n';
}
// Our function for handling the signal
void signal_handler(int signal) {
if (signal == SIGINT) {
msgOut();
std::exit(EXIT_SUCCESS);
}
}
class CountTime {
void m_start_count(){
std::this_thread::sleep_for(std::chrono::seconds(5));
}
public:
CountTime(){
std::signal(SIGINT, signal_handler); // Configuring signal handling
std::cout << "The 5 second countdown has started!" << '\n';
this->m_start_count();
}
~CountTime(){
msgOut();
}
};
int main(){
auto ct = std::make_unique<CountTime>();
return 0;
}After compiling and running, after pressing Ctrl + c, the output will now be:
The 5 second countdown has started!
^CThe 5 second count has finished.Note that after Ctrl + c(^C) the message appeared normally!
while#include <iostream>
#include <csignal>
void signal_handler(int signal) {
if (signal == SIGINT) {
std::cout << "You pressed: Ctrl + C\n";
std::exit(EXIT_SUCCESS);
}
}
auto main() -> int {
std::signal(SIGINT, signal_handler);
while (true){}
}Output after
Ctrl + c:
^CDou pressed: Ctrl + CI hope it helped, for more information visit documentation about std::signal.