How to handle a ctrl-break signal in a command line interface - c++

Before I begin, I want to clarify that this is not a command-line tool, but an application that accepts commands through it's own command-line interface.
Edit: I must apologize about my explanation from before, apparently I didn't do a very good job at explaining it. One more time...
I am building a command-line interface application that accepts commands from a user. I have a signal handler setup to catch the signals, which then sets a flag that I need to terminate the application. The problem I'm having is all of the console functions I can find are blocking, which means that I can't detect that I need to exit from my console processing loop until the user presses a key (or enter, depending on the function).
Is there some standard way I can do either non-block console interaction, or is there an elegant way to structure the program so that if I just terminate from the signal thread, that everything will be handled and released properly (please don't mis-understand this, I know how this could be done using locking and releasing the resources from the signaling thread, but this could get messy, so I'd rather avoid it)
Hopefully that explanation makes more sense...

OK - this is working for me on Windows & is portable - notice the #ifdef SIGBREAK - this isn't a standard signal.
#include <csignal>
#include <iostream>
#include <ostream>
#include <string>
using namespace std;
namespace
{
volatile sig_atomic_t quit;
void signal_handler(int sig)
{
signal(sig, signal_handler);
quit = 1;
}
}
int main()
{
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
#ifdef SIGBREAK
signal(SIGBREAK, signal_handler);
#endif
/* etc */
while (!quit)
{
string s;
cin >> s;
cout << s << endl;
}
cout << "quit = " << quit << endl;
}

On *nix, you can use the signal function to register a signal handler:
#include <signal.h>
void signal_handler(int sig)
{
// Handle the signal
}
int main(void)
{
// Register the signal handler for the SIGINT signal (Ctrl+C)
signal(SIGINT, signal_handler);
...
}
Now, whenever someone hits Ctrl+C, your signal handler will be called.

In Windows: SetConsoleCtrlHandler

On a *nix based system you might not really need a signal handler for this to work. You could specify that you want to ignore the SIGINT call
int main(void)
{
// Register to ignore the SIGINT signal (Ctrl+C)
signal(SIGINT, SIG_IGN);
while(1)
{
retval = my_blocking_io_func();
if(retval == -1 && errno == EINTR)
{
// do whatever you want to do in case of interrupt
}
}
}
The important way that this works is to recognize that non-blocking functions do get interrupted. Normally, you would realize that the blocking function failed (e.g. read()) and reattempt the function. If it was some other value you would take the appropriate error related action.

A better *nix solution that is thread safe is to use pthread_sigmask() instead of signal().
For example, this is how you signore SIGINT, SIGTERM, and SIGPIPE in the current thread and future spawned threads:
sigset_t waitset;
sigemptyset(&waitset);
sigaddset(&waitset, SIGINT);
sigaddset(&waitset, SIGTERM);
sigaddset(&waitset, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &waitset, NULL);

Related

How to wait for signal to term executable

I would like to put my main thread to sleep until the application is terminated externally, I think it would be best with sigwait() or sigwaitinfo().
What signals would I need to respond to and how might this look? I'm a bit exhausted by the abundance of examples, or am I imagining the whole thing too easy?
So you want to make some actions before you application is terminated (with SIGTERM). For this you can register a SIGTERM handler, short example:
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
void sig_handler(int signum)
{
printf("\nDo some signal handling actions here\n");
exit( 0 );
}
int main()
{
signal( SIGTERM, sig_handler ); // Register signal handler
getchar();
return 0;
}

Using a signal listener thread - how do I stop it?

A snippet from my main method:
std::atomic_bool runflag;
// ...
std::thread signaller([&]() mutable {
while (runflag) {
int sig;
int rcode = sigwait(&set, &sig);
if (rcode == 0) {
switch (sig) {
case SIGINT: {
// handle ^C
}
}
}
}
});
while (runflag) {
next = cin.get();
// handle character input
}
signaller.join();
I'm using the sigwait()-based approach for detecting SIGINT sent from the command line.
The signaller thread uses sigwait() to listen for signals. The program terminates when runflag is set false. However, the signaller thread will still be blocked at sigwait when this happens. I don't think I can use condition variables, as sigwait has no way to hook into one. Is there an alternative solution that is preferably not Linux-only?
EDIT 1: Alternatively, is there an interruptible version of sigwait?
You can use the sigtimedwait() function, which returns after a timeout given as a parameter.
You will need to check the return value from sigtimedwait() to check if it finished because of timeout or the signal arrived and then depending on this value you will need to handle signal or just check runflag and run again sigtimedwait().
Here is more about it from another answer: https://stackoverflow.com/a/58834251/11424134
You can wake up the signal-handling thread by having the process send another signal to itself, eg.
kill(getpid(), SIGUSR1);

Why is signalhandler not outputting anything?

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;
void sighandler(int sig) {
cout << "signal received" << endl;
}
int main() {
int pid= getpid();
cout << pid << endl;
signal( SIGUSR1, sighandler );
sigset_t accept;
sigaddset( &accept, SIGUSR1 );
int s;
sigwait(&accept, &s);
cout << s << endl;
return 0;
}
When I run this program and send a SIGUSR1 signal to it via "kill -s SIGUSR1 $pid" it just outputs the number of the signal (10) but not the text in sighandler. I don't understand why. This is on a Linux System.
From sigwait - wait for queued signals
DESCRIPTION
The sigwait() function selects a pending signal from set, atomically clears it from the system's set of pending signals, and returns that signal number in the location referenced by sig.
So, by using sigwait(), the signal is already delivered and dealt with by your program.
When you remove the sigwait call and do a sleep or busy waiting, the SIGUSR1 signal will be delivered to your signal handler and the message "signal received" will be printed.
You're getting this behavior because when you call sigwait() your thread gets put to sleep and control gets passed to the OS. When you send the SIGUSR1 signal, it is getting handled by the OS, and then the OS wakes up your thread and passes control back. Even though you've registered a signal handler, your handler is not getting called because the signal has been handled by the time your thread is re-awakened.
I am trying to find a definitive reference, but it appears that the signal handler and sigwait are mutually exclusive. If you handle the signal synchronously, using sigwait, the handler is never invoked.
For a discussion, see About the ambiguous description of sigwait()

C++: How do I check if my window is about to close?

I'm trying to make a Win32/*nix console-based ASCII game. I want to use no libraries whatsoever that aren't standard C++ or on *nix/windows(.h).
I want it to be structured like a game loop. Aka:
while (!WIN_CLOSE_FUNCTION()) {
//Do crap
}
//Do other shutdown crap
return 0;
Can anyone point me to what function this would be? If it is platform dependent, give me one example on Windows and *nix.
For the Unix/Linux console, there is no such function. The closest you can do is to catch the signal SIGHUP which is sent when losing the terminal. However be aware that the things you can do in a signal handler are quite limited. Probably the closest to your loop would be (note: untested code):
#include <signal.h>
volatile sig_atomic_t hupflag = 0;
extern "C" void hangup(int)
{
hupflag = 1;
}
int main()
{
sigaction act;
act.sa_handler = hangup;
act.sa_mask = 0;
act.sa_flags = 0;
if (sigaction(SIGHUP, &act, 0) < 0)
{
std::cerr << "could not install signal handler\n";
return 1;
}
while (!hupflag)
{
// ...
}
// shutdown
return 0;
}
Similar question that might help you What happens when you close a c++ console application
The accepted answer is:
Closing a c++ console app with the "x" in the top corner throws an CTRL_CLOSE_EVENT which you could catch and process if you set a control handler using the SetConsoleCtrlHandler function.
Useful links:
Console Event Handling
SetConsoleCtrlHandler
On *nix:
On Linux and other Unix systems, the console runs as a separate process. As you close the shell, it sends the SIGHUP signal to the currently active process or processes that are not executed in the background. If the programmer does not handle it, the process simply terminates. The same signal is sent if you close the SSH session with a terminal and an active process.
answer provided by #Zyx in the question linked above
There isn't such a function per se, but both Unix and Windows will send
a signal (SIGHUP under Unix, SIGBREAK under Windows) to all
processes in the process group when the window on which the process
group depends is closed. So all you have to do is catch the signal and
set a flag, which you test in the loop:
#ifdef _WIN32
int const sigClosed = SIGBREAK;
#else
int const sigClosed = SIGHUP;
#endif
volatile sig_atomic_t windowClosed = 0;
void signalHandler( int )
{
windowClosed = 1;
}
// ...
signal( sigClosed, signalHandler );
while ( windowClosed == 0 ) {
// ...
}
If you're doing any input from the console in the loop, you'll have the
be prepared for the input to fail (which you should be anyway).

gSoap: how to gracefully shutdown the webservice application?

I'm using gSoap to write a webservice. It's running as a console application. In all gSoap examples I see, that requests are dispatched in infinite loop like for(;;;) even in multi-threaded version.
But how can I make my webservice to terminate gracefully when, say, user presses space on the console?
Preferably:
stop accepting new connections;
Serve existing ones;
Exit from application
The only solution I came up so far is using timeouts
soap->recv_timeout = 20;
soap->send_timeout = 20;
soap->connect_timeout = 5;
soap->accept_timeout = 5;
Then all blocking functions return periodically. But this is not ideal for me, because I want to be able to terminate the app quickly even if there is an ongoing transmission, but at the same time, don't want to compromise reliability on a slow/flaky connection (it's an embedded device connected via GPRS).
The section 7.2.4 How to Create a Multi-Threaded Stand-Alone Service in the documentation has example code for writing an accept loop. You need to write your own accept loop and add signal handling so it responds to Ctrl-C.
stop accepting new connections:
Leave the loop so you stop calling accept.
Serve existing ones:
The threads need to inform you when they are finished, so you can exit when the number of active clients is zero. (boost::thead_group has a join_all which does exactly that.)
Exit from application:
What you need to do is register signal handler so when you terminate your application using Ctrl + C, it calls you registered function where you can gracefully terminates.
e.g
class gsoap_test {
public:
void start() {
running_ = true;
while(running_) {
//gsoap threads
}
//stop and cleanup
}
void stop() {
running_ = false;
}
private:
bool running_;
};
//global variable
gsoap_test gsoap;
void sighandler(int sig)
{
std::cout<< "Signal caught..." << std::endl;
//Stop gracefully here
gsoap.stop();
exit(0);
}
int main(int argc, char** argv) {
//register signal
signal(SIGABRT, &sighandler);
signal(SIGTERM, &sighandler);
signal(SIGINT, &sighandler);
gsoap.start();
return EXIT_SUCCESS;
}