I have this simple code that loops the word "SIGNALS ARE COOL" I'm trying to make it take signals like (SIGFPE. SIGABRT, SIGINT, SIGSEGV.) and show the signal type and the time I made this code that takes "SIGINT" signal how do I add more signals and how to control what my program show when the signals are triggered by the user.
// ConsoleApplication3.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <csignal>
using namespace std;
void signalHandler(int signum) {
cout << "Interrupt signal (" << signum << ") received.\n";
// cleanup and close up stuff here
// terminate program
exit(signum);
}
int main() {
// register signal SIGINT and signal handler
signal(SIGINT, signalHandler);
while (1) {
cout << "SIGNALS ARE COOL" << endl;
}
return 0;
}
I see that this looks like an assignment; so what I'm saying may not be relevant to you (but might be to someone someday).
--EDIT--
I see you've also got stdafx.h, which I think is a Visual Studio Windows thing, and here I am suggesting a POSIX solution (not pure C++). I didn't read carefully enough, and that invalidates my whole answer (I think). You probably can't use my suggestion, and for that I'm sorry.
However, I'm going to leave it here in case someone one day finds this and needs to work with signals in a Unix system.
--
I've found that it's often a lot more practical to avoid signal handling functions like this altogether, and take signals on your own terms. As noted by others, there's a lot of rules about what you can and can't do within a signal handler, because they can be invoked at any time, in any thread, unless you take extra precautions. I've seen this result in a lot of messy code, things like 'have a global bool got_signal that gets checked by things all over the application to know if they're supposed to shut down'. There's obviously nice ways to do signal handling, but at this point I try to avoid it altogether in favor of other options.
The functions pthread_sigmask and sigwait can be used to invert control here and allow you to accept signals within the defined flow of program execution where you want it, and then you don't need to worry about taking invalid actions when you handle them. Using pthread_sigmask you can tell the OS not to interrupt your program to deliver signals and instead queue them up, and then sigwait can be used to handle them at an appropriate time. You can't do this with all signals (some things like kill -9 and a SEGFAULT can't/shouldn't be ignored), but it works well for most of them.
Using an approach like this, it's really easy to interact with signals in a larger application too. You can block signals at the start of main, and that will propagate to all children threads, and then you can designate one specific child thread to just wait for signals an pass events into the rest of the application in whatever method is appropriate for the framework of your application.
#include <signal.h>
#include <unistd.h>
#include <initializer_list>
#include <functional>
#include <algorithm>
#include <iostream>
sigset_t make_sigset(std::initializer_list<int32_t> signals)
{
sigset_t set;
const int32_t result = sigemptyset(&set);
std::for_each(signals.begin(), signals.end(), std::bind(&sigaddset, &set, std::placeholders::_1));
return set;
}
int main()
{
const auto signal_list = make_sigset({SIGTERM, SIGSEGV, SIGINT, SIGABRT});
pthread_sigmask(SIG_BLOCK, &signal_list, nullptr);
int32_t last_signal;
do
{
sigwait(&signal_list, &last_signal);
std::cout << "Got signal " << last_signal << std::endl;
// Exit on sigint so ctrl+c still works
} while (last_signal != SIGINT);
return 0;
}
As already mentioned by #Eljay in the comments, you have to be careful with the things you do in a signal handler.
I'd also suggest not using namespace std, but that's a story for another time link.
I'd recommend you this page which explains a lot about what signals can and cannot do, according to the c++ standard. Now what they actually do in your compiler (which I assume is MSVC) may be different.
Some of the important bits, as already mentioned, you shouldn't do I/O, you shouldn't throw, etc...
To answer your question, you were on the right track, adding other signals can be done via:
// catch SIGTERM
std::signal(SIGTERM, signalHandler);
std::signal(SIGSEGV, signalHandler);
std::signal(SIGINT, signalHandler);
std::signal(SIGABRT, signalHandler);
// insert others
Then, what I'd suggest is storing the value of your signal into some atomic variable, like: gSignalThatStoppedMe.
std::atomic<int> gSignalThatStoppedMe = -1;
// I also added 'extern "C"' because the standard says so
extern "C" void signalHandler(int signum) {
gSignalThatStoppedMe.store(signum);
}
Then, your while loop would check for != -1, or pick another value for this, I've not checked if some implementations use -1 as a valid value for signals
// ...
while(gSignalThatStoppedMe.load() == -1)
{
// your old code
}
Now, do a switch of sorts, with the values inside and output the signal that stopped it, something like:
switch(gSignalThatStoppedMe.load())
{
case SIGINT:
std::puts("It was SIGINT");
break;
case SIGTERM:
std::puts("It was SIGTERM");
break;
default:
break;
}
I think this has less undefined behavior, which is always a good thing.
EDIT: here's a compiler explorer link
The output with CTRL-C:
SIGNALS ARE COOL
SIGNALS ARE COOL
SIGNALS ARE COOL
SIGNALS ARE COOL
SIGNALS ARE COOL
SIGNALS ARE COOL
SIGNALS ARE COOL
SIGNALS ARE COOL
SIGNALS ARE COOL
Interrupt signal SIGINT (2) received.
Related
My Ncurses app is looping for keyboard input and prints output to the screen. When I'm stopping my app (ctrl+z) and later resuming it, I have noticed that input buffer sometimes contains unwanted characters. So I want to enrich SIGCONT handler by default provided by ncurses with flushinp(), simplified code below:
#include <csignal>
#include <curses.h>
#include <stdlib.h>
#include <fstream>
struct sigaction oldact, newact;
extern "C" void sigContHandler(int sig)
{
std::ofstream of("sc", std::ofstream::app);
of << "Handling cont " << std::endl;
flushinp();
//Call old handler, but crash as it is always 0
(oldact.sa_handler)(sig);
}
int main(void)
{
initscr();
cbreak();
noecho();
clear();
newact.sa_handler = sigContHandler;
newact.sa_flags = 0;
sigemptyset (&newact.sa_mask);
sigaction(SIGCONT, &newact, &oldact);
int c = 0;
while (c = getch()) {
if (c == 'q')
break;
mvaddch(0, 0, c);
}
refresh();
endwin();
exit(0);
}
I can't call old SIGCONT handler as it is always 0. Obviously this default handler is successfully called if I don't add code to chain signal handlers. I don't understand why I can't call old handler, what am I doing wrong?
I find nothing in flushinp's documentation that indicates that it is signal-safe. Because of what signals are, and how they work, by default any library functions -- especially third party libraries -- are presumed by default to be not signal safe unless documented otherwise. As such they cannot be called from an asynchronous signal handler.
Note, for example, that the signal-safety(7) manual page explicitly enumerates the only C library functions that are signal-safe. Unless the function is on the list, it cannot be called from a signal handler. None of the C++ library classes, templates, and functions, are signal-safe.
If all your signal handler did was called the original handler (if it was not NULL, and do nothing if it was NULL), it would be fine. But the invocation of flushinp introduces undefined behavior, and that's the end of the line.
The only way to do this safely, on Linux, is to use a signal file descriptor, effectively turning an asynchronous signal handler into a file descriptor event, and implement multiplexed non-blocking poll loop for standard input and the signal file descriptor, integrated with the curses library. This is quite complicated, and will require quite a bit of work. It is also unclear what is the source of your unwanted input. Input doesn't materialize out of thin air, so there must be a reason for that, and you might want to look in that direction, first, instead of attempting to address the effect, rather than the cause.
In the question are std::signal and std::raise thread-safe? are there some comments to differentiate communication of inter-process from that of multi-threads. I'd like assent on opinion that signal be used only in case of IPC by its nature. However, developers always need to set signals for their programs, no matter if they decide IPC or multi-threaded paradigm to apply afterwards, as to handle signals that OS raises.
So my question is about what shall developers do to handle signals in that case - that is, for example, we'd like a multi-threaded program exit upon signal arises. ("Talk is cheap, show me the code")
//C++11 standard conformance
#include <csignal>
#include <thread>
void function(){
//some a loop
while(/* predicate to exit */)
{
//...
}
}
//we might wish to flag a volatile variable in the following handler for asynchronous thread of this program to judge on to exit. But it's not certainly that thread of handler rather than function blocks on these signals! (O.o)
void handler(int signal){
switch(signal){
case SIGINT: //...upon interruption
case SIGTERM: //...upon termination
case SIGQUIT: //...upon quit
}
}
int main(int argc, char * argv[]){
std::signal(SIGINT, handler);
std::future<void> result=std::async(std::launch::async, function);
return 0;
}
The framework may be self-explanatory to you. Shall I presume that it's always the thread of handler rather than function to block on signal? What shall I do to terminate this program in general?
I have a console server which listens clients and does what they need. But sometimes I need end server and I don't know how I can do it properly. Because I can hit ctrl+c to end program, but I have important code after loop which I need to do.
main_function(){
while(true){
listen();
}
do_something_important();
}
Can I catch some signal from console and run function to do important stuff and properly end?
end_program(){
do_something_important();
return 0;
}
Or what is the best way what I can do in my situation?
Use signals like Pragmateek described, but make sure to only set a flag in your signal handler (like exitnow = true), and check for this flag in your main loop. Signals may interrupt your main program at any point in your code, so if you want to be sure that your logic is not going to be randomly interrupted or cut short, use signal handlers just to set flags.
You could use signals:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
static void on_close(int signal)
{
puts("Cleaning up...");
exit(EXIT_SUCCESS);
}
int main(void)
{
signal(SIGINT, on_close);
while (1)
{
}
return EXIT_SUCCESS;
}
So here is my code:
void sigHandle(int sig)
{
signal(SIGINT, sigHandle); //Is this line necessairy?
cout<<"Signal: "<<sig<<endl;
}
int main(){
signal(SIGINT, sigHandle);
while(true){ //Supposed to loop until user exits.
//rest of my code
}
}
Now it is my understanding of signal() that when the SIGINT command (Ctrl+C right?) is received my function sigHandle should be called with an integer value of 2 (the SIGINT number), the method should run and the program should NOT exit.
All I would like to do is just print the signal number and move on, however after printing out "Signal: 2" it exits.
(Eventually I'm supposed to handle the first 32 interrupts but I figured Ctrl+C would be the most difficult so I'm starting here.)
In main if I do signal(SIGINT, SIG_IGN); it ignores the signal correctly and doesn't exit but I now have no way of knowing if I recieved the SIGINT interrupt.
Earlier I was playing around with the sigaction struct but I could not find any real comprehensive documentation on it so I decided to go with just "raw" signal handling.
This was my sigaction code (same problem as above):
struct sigaction action;
action.sa_handler = sigHandle;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
sigaction(SIGINT, &action, 0);
Thanks for your help!
EDIT
OK SO After many many many hours of scowering through man pages and the internet I have happened across a (very) ghetto solution involving saving the stack pre-infinite loop then when the interrupt comes, doing what I need to do, then re-setting the stack back to where it was and calling the sigrelse() command to re-set any states that might have been changed and not re-loaded.
I understand that this is not the most elegant/efficient/or even socially acceptable solution to this problem but it works and as far as I can tell I am not leaking any memory anywhere so it's all good...
I am still looking for a solution to this problem and I view my stack re-setting shenanigins as only a temporary fix...
Thanks!
Also note you should not call stdio (or other non-reentrant functions) in signal handlers.
(your signal handler might be invoked in the middle of a malloc or it's C++ equivalent)
It is not. You just replacing SIGINT's handles with same function. How does you program perform wait?
If you have something like:
int main
{
// ...
int r = read(fd, &buff, read_size); // your program hangs here, waiting for the data.
// but if signal occurred during this period of time
// read will return immediately, and r may != read_size
return 0; // then it will go straight to return.
}
I have a c++ application linked against some c libraries.
Are there possible approaches to encapsulate the signal handling in a C++ class, so it could be handled as a c++ exception?
You can't and if you could a lot of things would break.
What you should do is set a flag in the signal handler, periodically check in your code and throw an exception when you detect the flag is set.
Such an approach is similar to how threads get interrupted in Boost.Threads, which I strongly suggest you study.
Signal handling is something very tighten on the OS level, it is generally do not used
for "error" handling unless they are SIGSEGV or SIGFPU that usually result that very bad things happened to program, but rather used to alarm on specific events that happened in system.
Also in signal handler you can perform very limited tasks, only few system calls are actually signal safe.
So, generally don't throw as a result of signal ;-)
If you mean if want throw an exception at an arbitrary point of code when the signal is delivered to the process, you can't. The signal is delivered in a different execution context, so your original thread won't catch it.
Even if you could, you shouldn't, as any assumptions about atomicity of your operations and exception safety guarantees would go out of the window.
As pointed out several times, doing this is general not a good idea. If you really want to do this, here is something I wrote a little while ago.
#include <signal.h>
#include <exception>
#include <iostream>
//template class that translates a signal in an exception
//the given SignalExceptionClass should have a static int signalNumber()
template<class SignalExceptionClass>
class SignalTranslator
{
private:
class SingletonTranslator
{
public:
SingletonTranslator()
{
signal(SignalExceptionClass::signalNumber(), handler);
}
static void handler(int)
{
throw SignalExceptionClass();
}
};
public:
//sigleton pattern so we don't install more than one handler
//for a given signal
SignalTranslator()
{
static SingletonTranslator translator;
}
};
//example for SIGFPE
class FloatingPointException : public std::exception
{
public:
static int signalNumber() {return SIGFPE;}
const char* what() const throw() {return "Floating point exception";}
};
//install translators
static SignalTranslator<FloatingPointException> fpeTranslator;
int main()
{
try
{
std::cout << "causing SIGFPE\n";
std::cout << 1 / 0 << std::endl;
}
catch (std::exception& e)
{
std::cout << e.what() << std::endl;
}
std::cout << "after SIGFPE\n";
}
In this example, every time a SIGFPE is raised, a FloatingPointException will be thrown. Running the example will output the following:
causing SIGFPE
Floating point exception
after SIGFPE
Note: this will not work for all types of signals. For example, it does not work for SIGSEGV.
It sounds like you try to do something terribly wrong. Generally, do not do signals unless there is a special reason for it. Signal are there more for admin than for software developers.
Otherwise, it is quite complicated (and generally impossible) to map signals to exceptions, as OS is allowed to merge some signal. E.g. SIGCHLD would happen only once if two child processes had terminated simultaneously. And you can't schedule to throw two exceptions - one after another.
Another point would be that signal is allowed to be delivered to any thread in multi-threaded application. One thing is throwing exception. But you might run eventually into the problem of actually catching the exception precisely where you want it.
Beyond standard clean-up on termination and reaping the children - do not toy with signals. Modern *NIX allow to do pretty much everything application needs without signals.
I might have a solution for you.
I am developing exception4c, an exception handling framework for C. It can turn system signals into exceptions. For example, it lets you catch SIGSEGV this way:
int * pointer = NULL;
try{
int oops = *pointer;
}catch(BadPointerException){
printf("No problem ;-)");
}
These exceptions are not C++ exceptions, though. The library is standard ANSI C (C89).