SIGINT handler reset in Visual C++ 2015 - c++

Consider the following test program
#include <csignal>
#include <iostream>
volatile std::sig_atomic_t signal_raised = 0;
void set_signal_raised(int signal) {
signal_raised = 1;
}
void check(std::sig_atomic_t expected) {
if (signal_raised != expected) {
std::cerr << signal_raised << " != " << expected << std::endl;
abort();
}
}
int main() {
using namespace std;
check(0);
std::signal(SIGINT, set_signal_raised);
check(0);
std::raise(SIGINT);
check(1);
signal_raised = 0;
check(0);
std::raise(SIGINT);
check(1);
cerr << "OK.\n";
}
With GCC and Clang, it outputs "OK." However, with Visual Studio 2015, it outputs nothing.
The signal handler is reset after handling the first signal. This can be verified by adding
auto prev = std::signal(SIGINT, set_signal_raised);
if (prev != set_signal_raised) {
std::cerr << "Unexpected handler." << std::endl;
abort();
}
to the check function. Is this allowed and expected?

Reset of the signal disposition is the behaviour that Unix System V used. But the BSD (currently glibc) do not reset the signal disposition. Either behaviour is allowed by POSIX standard allowed. C standard doesn't specify whether the "reset" is allowed.
From signal(2):
POSIX.1 solved the portability mess by specifying sigaction(2), which
provides explicit control of the semantics when a signal handler is
invoked; use that interface instead of signal().
In the original UNIX systems, when a handler that was established
using signal() was invoked by the delivery of a signal, the
disposition of the signal would be reset to SIG_DFL, and the system
did not block delivery of further instances of the signal. This is
equivalent to calling sigaction(2) with the following flags:
sa.sa_flags = SA_RESETHAND | SA_NODEFER;
System V also provides these semantics for signal(). This was bad
because the signal might be delivered again before the handler had a
chance to reestablish itself. Furthermore, rapid deliveries of the
same signal could result in recursive invocations of the handler.
So, it seems Visual studio follows the System V behaviour.
Is this allowed and expected?
It's allowed but certainly not desired. For this reason, POSIX introduced sigaction(). If you have sigaction() then use it.
Otherwise, you just need to reinstall the handler everytime inside the signal handler:
void set_signal_raised(int signal) {
std::signal(SIGINT, set_signal_raised);
signal_raised = 1;
}

Related

Toggling logging functionality using signals on a multithreaded program

I am looking to put in some code (temporary at the moment, but as a thought experiment, I am considering working it in long term), that would accomplish two things.
Allow toggling of logs via signals.
Trap all catchable signals and output pid/thread/signal info to the logs, followed by returning to default behavior.
here is some compiling pseudo-code which shows what I would like to achieve.
#include <iostream>
#include <csignal>
#include <thread> // for this_thread
#include <unistd.h> // For gitpid() and fork()
#include <cstdlib>
// What is a save way of determining the number of
// available signals
// ** Externally defined values
const int verbose_debug_signal = 30;
const int trace_logging_enabled_default = 0;
// ** Component Control Class Definition Start
volatile sig_atomic_t trace_logging_enabled
= trace_logging_enabled_default;
void handle_signal(int sig)
{
std::cout << "Process PID: " << std::dec << getpid()
<< " Caught signal " << std::dec
<< sig << " on thread 0x" << std::hex
<< std::this_thread::get_id() << "\n";
if(sig == verbose_debug_signal)
{
trace_logging_enabled = ~trace_logging_enabled;
std::cout << "Trace Logging "
<< (!!trace_logging_enabled ? "enabled\n" : "disabled\n");
}
else
{
signal(sig, SIG_DFL);
raise(sig);
}
}
class ComponentControlClass
{
public:
ComponentControlClass()
: trace_logging_enabled_ptr(&trace_logging_enabled)
{}
~ComponentControlClass(){}
private:
volatile sig_atomic_t *trace_logging_enabled_ptr;
};
int main()
{
for(int i = 1; i < NSIG; ++i)
{
signal(i, handle_signal);
}
// BAH! stupid SIP strikes again. I think I would
// have to sign this to make it work.
// pid_t children[3];
// for(auto child : children)
// children[child] = fork();
while(1);
return 0;
}
Compiled with the -O3 flag to make sure Volatile fields don't get clobbered. The result of running the code in window 1 and sending a "kill -30 " in window 2, exactly 4 times:
Process PID: 46008 Caught signal 30 on thread 0x0x11325f600
Trace Logging enabled
Process PID: 46008 Caught signal 30 on thread 0x0x11325f600
Trace Logging disabled
Process PID: 46008 Caught signal 30 on thread 0x0x11325f600
Trace Logging enabled
Process PID: 46008 Caught signal 30 on thread 0x0x11325f600
Trace Logging disabled
This is exactly what I hoped would happen. In this example this class would represent a component control class which is the entry point for our shared objects using a homegrown framework. In other words, this is where I would need to pass external elements to the schema, like a pointer to volatile memory indicating the log state?
My question(s)
I've never seen anyone do anything like this so I am certain there is a good reason. I am trying to understand the implications.
I found a few articles on complex signal handling, and I was having trouble determining what applied. For all other signals aside from the one I am using to toggle I am trapping and re-enabling, so I wouldn't think this would be an issue. Is it?
When the toggling signal is sent I would want to propagate the logging state to
child processes. I haven't been able to simulate this easily on my Mac because of
SIP, but I haven't quite figured out how I would do this. Only confirmation that it won't happen by itself, because signals work on a per-thread basis.
Now that I'm bouncing between linux and Mac, I am seeing that signal.h is pretty different. My main concern is that different macros are used for the max interrupt and apple seems to only have 32 interrupts where linux uses 64. Is there a boilerplate way of approaching the signals (specifically the max/min values) which is more portable? Something like this but hopefully more robust:
int sigma = 0;
#ifdef LINUX
sigmax = _NSIG;
#elif APPLE
sigmax = NSIG;
#endif

gRPC: How can RPC handlers properly detect if `Server` has been `Shutdown()`

Current, I'm using a hackish way – a global variable – to make RPC handlers able to detect that the Server has been (about to be) called Shutdown().
bool g_ServerIsNotDead = true; // Hack!
Status StreamServiceImpl::GetCurrentTemperature(ServerContext *context_,
const UpdateInterval *request_,
ServerWriter<Temperature> *stream_)
{
auto currentTemp = 100.0f;
while(g_ServerIsNotDead) // Hack!!!
{
qDebug() << QThread::currentThreadId() << currentTemp << "farenheit.";
Temperature message;
message.set_temperature(currentTemp);
stream_->Write(message);
QThread::sleep(2);
currentTemp += 1.0f;
}
return Status::OK;
}
void insideSomeFunction() {
// Testing shutdown 5 seconds later
QTimer::singleShot(std::chrono::seconds(5), this, [=]() {
qDebug() << "Shuting down!";
g_ServerIsNotDead = false; // Hack!!
this->server->Shutdown(); // This method actually blocks until all RPC handlers have exited, believe it or not!
emit shutdown();
qDebug() << "All dead.";
});
}
Ref: https://github.com/C0D1UM/grpc-qt-example/blob/master/rpc_server/hellostream_server.cpp
It would be really nice if I could somehow check that Server has been Shutdown() from grpc::ServerContext, but I didn't see any relevant methods to achieve this.
Even better if someone could propose a way to take out the while loop completely (?). I'm using Qt so everything is event-driven.
So, I think it's worth making clear what Shutdown does. There's a detailed comment about this but basically, server Shutdown doesn't fail, cancel, or kill your existing in-progress calls (unless you use the deadline argument and the gRPC C++ async API).
Rather, it stops listening for new connections, stops accepting new calls, fails requested-but-not-yet-accepted calls. If you want to fail or terminate your calls at shutdown, you can do it at application-level code as you've done above.
I would just recommend that instead of using a global variable, you should use a member function of your StreamServiceImpl class so that you can support multiple services running in the same process if you choose.
We can use ServerContext::IsCancelled as a breaking/termination criteria in streaming APIs. I changed GetCurrentTemperature(...) as follows (just replaced g_ServerIsNotDead with !context_->IsCancelled()) and it worked:
Status StreamServiceImpl::GetCurrentTemperature(ServerContext *context_,
const UpdateInterval *request_,
ServerWriter<Temperature> *stream_) {
auto currentTemp = 100.0f;
while(!context_->IsCancelled) {
qDebug() << QThread::currentThreadId() << currentTemp << "farenheit.";
Temperature message;
message.set_temperature(currentTemp);
stream_->Write(message);
QThread::sleep(2);
currentTemp += 1.0f;
}
return Status::OK;
}

Why is a signal handler I establish with signal() or sigaction() ignored?

I've got the following issue: I would like to catch SIGINT (and later, also SIGTERM) signals while my code is running on my Raspberry Pi 3 (with the recent Raspbian) in order to do some clean-up (particularly, closing a connection to a USB device) when I stop my (C++ 11) program. First I tried out signal (), but the signal handler never kicked in. Instead, I got this message on my console after hitting ^C:
2017-02-26 17:13:17 sigHandler: Unhandled signal 2, terminating
The signal manpage recommends to use sigaction() instead. OK, I took this tutorial to replace signal() with sigaction(), but no use, the handler is never called. After reading a bunch of other tutorials (like this one), I finally ended up with this code snippet:
void OnSignalCaught (int signal)
{
cout << "Exited." << endl;
exit (signal);
}
int main ()
{
struct sigaction exit_action;
struct sigaction old_action;
int ret;
sigemptyset (&exit_action.sa_mask);
exit_action.sa_handler = OnSignalCaught;
exit_action.sa_flags = 0;
ret = sigaction (SIGINT, &exit_action, &old_action);
if (ret < 0) cout << "Creating signal handler failed! Error code: " << errno << "." << endl;
// remainder of the code goes here
}
I have been running exactly your code. I only added the missing headers, and it works, the signal hangler got called.

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).

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

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);