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.
Related
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.
I have simplified my example for an easier explanation. I am writing an application that counts to 100 but at any given time I allow the user to cancel the program by entering ctrl+c through the keyboard.
What seemingly started as a simple program quickly became complicated based on my lack of knowledge on function pointers. This is what I'm attempting to do:
Capture the SIGINT signal when ctrl+c is pressed.
Once captured, call a member function that shuts down a third-party resource.
The catch is that unlike the two examples that Michael Haidl and Grijesh Chauhan give on capturing SIGINT, I am not permitted to store any global variables. The ideal scenario is one in which all variables and function calls related to signal() are encapsulated within a class of mine.
Here's my modified attempt based on Haidl and Grijesh's code:
#include <thread>
#include <chrono>
#include <functional>
#include <iostream>
#include <signal.h>
class MyClass {
public:
volatile sig_atomic_t cancel = 0;
void sig_handler(int signal) {
cancel = true;
this->libCancel();
}
void libCancel() { std::cout << "Cancel and cleanup" << std::endl; }
};
int main(int argc, char *argv[]) {
MyClass mc;
//using std::placeholders::_1;
//std::function<void(int)> handler = std::bind(&MyClass::sig_handler, mc, _1);
//signal(SIGINT, handler);
signal(SIGINT, &mc.sig_handler); // **compiler error**
for (int i = 0; !mc.cancel && i < 100; ++i)
{
std::cout << i << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}
As you can see, I'd like the code to simply count to 100 and exit if all goes well. But if the user calls ctrl+c then the class should handle SIGINT, call the external library for cleanup, and the for loop will exit.
The main problem is that I can't seem to setup the signal() declaration to bind to my instance of MyClass::sig_handler. I even tried casting my member function to std::function to be used by signal(), commented out, but the compiler isn't happy about the fact that C++ function<void(int)> isn't equivalent to the C lang void (*)(int).
Any and all criticism is welcome. I'm not at all tied to what I've written and I clearly don't have a great fundamental understanding of how to use function pointers with member functions.
It is not possible to communicate between the signal handler and the rest of the program using local variables. No parameters are passed into the handler other than the raised signal and the handler returns no value.
The words "global variables" are somewhat ambiguous. People sometimes mean different things depending on context. If your restriction applies only to the global scope, then simply use a volatile sig_atomic_t within some namespace. Or use static member variable, if you so prefer.
If your restriction applies to static storage duration, then you can use a thread local variable instead.
If your restriction applies to all global memory, then your problem is unsolvable using a signal handler. You simply need a global variable of some sort.
If you can rely on POSIX rather than C++ standard, A way to handle SIGINT without globals is to make sure that it is not handled, and block the thread with sigwait. If the call returns SIGINT, then stop the program, otherwise do what you want to do with the signal that was caught.
Of course, this means that the blocking thread doesn't do anything other than wait for signals. You'll need to do the actual work in other thread(s).
Technically though, global memory is probably still used. The use is simply hidden inside system library.
Furthermore, it is not safe to use std::cout within a signal handler. I know that is only an example, but "call the external library for cleanup" is very likely also async signal unsafe.
This can be fixed simply by calling the cleanup outside the for loop rather than inside the handler.
The main problem is that I can't seem to setup the signal() declaration to bind to my instance of MyClass::sig_handler.
That's because signal requires a function pointer (of type void(int)). Non-static member functions cannot be pointed by function pointers. They can only be pointed by member function pointers, which signal doesn't accept.
I just tried the official example of libev, like below. After compiling and running, I see once I input anything from stdin, the event is triggered, no problem. But what I inputed is still treated as solid input and then appear on my console. My question is: is there a way to avoid this console input from being prompted to console, and just like libev to catch and store it?
Any way in libev can do this?
I paste the official example here:
// a single header file is required
#include <ev.h>
#include <stdio.h> // for puts
// every watcher type has its own typedef'd struct
// with the name ev_TYPE
ev_io stdin_watcher;
ev_timer timeout_watcher;
// all watcher callbacks have a similar signature
// this callback is called when data is readable on stdin
static void
stdin_cb (EV_P_ ev_io *w, int revents)
{
puts ("stdin ready");
// for one-shot events, one must manually stop the watcher
// with its corresponding stop function.
ev_io_stop (EV_A_ w);
// this causes all nested ev_run's to stop iterating
ev_break (EV_A_ EVBREAK_ALL);
}
// another callback, this time for a time-out
static void
timeout_cb (EV_P_ ev_timer *w, int revents)
{
puts ("timeout");
// this causes the innermost ev_run to stop iterating
ev_break (EV_A_ EVBREAK_ONE);
}
int
main (void)
{
// use the default event loop unless you have special needs
struct ev_loop *loop = EV_DEFAULT;
// initialise an io watcher, then start it
// this one will watch for stdin to become readable
ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ);
ev_io_start (loop, &stdin_watcher);
// initialise a timer watcher, then start it
// simple non-repeating 5.5 second timeout
ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.);
ev_timer_start (loop, &timeout_watcher);
// now wait for events to arrive
ev_run (loop, 0);
// break was called, so exit
return 0;
}
I assume you mean the echoing of what you write? It's the default behavior of terminal program. You can use termios functions and flags to disable echoing. Remember to enable it before exiting your program though.
In ev_io_init you are setting what your trigger will be. Instead of setting STDIN_FILENO you can choose to use a fd from a socket for example. Don't know if this is what you are looking for. Here you have an example of what I am saying.
In C++11, what is the safest (and perferrably most efficient) way to execute unsafe code on a signal being caught, given a type of request-loop (as part of a web request loop)? For example, on catching a SIGUSR1 from a linux command line: kill -30 <process pid>
It is acceptable for the 'unsafe code' to be run on the next request being fired, and no information is lost if the signal is fired multiple times before the unsafe code is run.
For example, my current code is:
static bool globalFlag = false;
void signalHandler(int sig_num, siginfo_t * info, void * context) {
globalFlag = true;
}
void doUnsafeThings() {
// thigns like std::vector push_back, new char[1024], set global vars, etc.
}
void doRegularThings() {
// read filesystem, read global variables, etc.
}
void main(void) {
// set up signal handler (for SIGUSR1) ...
struct sigaction sigact;
sigact.sa_sigaction = onSyncSignal;
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
sigaction(SIGUSR1, &sigact, (struct sigaction *)NULL);
// main loop ...
while(acceptMoreRequests()) { // blocks until new request received
if (globalFlag) {
globalFlag = false;
doUnsafeThings();
}
doRegularThings();
}
}
where I know there could be problems in the main loop testing+setting the globalFlag boolean.
Edit: The if (globalFlag) test will be run in a fairly tight loop, and an 'occasional' false negative is acceptable. However, I suspect there's no optimisation over Basile Starynkevitch's solution anyway?
You should declare your flag
static volatile sig_atomic_t globalFlag = 0;
See e.g. sig_atomic_t, this question and don't forget the volatile qualifier. (It may have been spelled sigatomic_t for C).
On Linux (specifically) you could use signalfd(2) to get a filedescriptor for the signal, and that fd can be poll(2)-ed by your event loop.
Some event loop libraries (libevent, libev ...) know how to handle signals.
And there is also the trick of setting up a pipe (see pipe(2) and pipe(7) for more) at initialization, and just write(2)-ing some byte on it in the signal handler. The event loop would poll and read that pipe. Such a trick is recommended by Qt.
Read also signal(7) and signal-safety(7) (it explains what are the limited set of functions or syscalls usable inside a signal handler)....
BTW, correctness is more important than efficiency. In general, you get few signals (e.g. most programs get a signal once every second at most, not every millisecond).
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.
}