I am trying to use the function signal(int,void(*)(int)) from <csignal> to handle the floating point exception SIGFPE. I’d like to be able to print some useful diagnostics besides just a message saying “Floating point exception” or something to that effect. This means the function I pass as the handler to signal needs access to some of the data in my code. Therein lies the rub.
The function must return void and accept only 1 parameter of type int. I cannot make the handler a member function of my data storage class since then the type would be void(Foo::*)(int) due to the hidden this pointer.
I thought about using lambdas to try and make an anonymous function like this;
void handler(int nSig, Foo data)
{
// do something
}
// snip
Foo data;
signal(SIGFPE, [&](int nSig)->void{handler(nSig,data);});
however because the lambda captures the variable data from outside the compiler will not let it be cast to a pointer to void(*)(int) (which is a shame as this seems like an ideal use for lambdas).
I could simply make data a global variable which could then be seen in handler but I am loath to do this for obvious reasons.
So my question is thus; what is the best way of mimicking anonymous functions in C++?
Note: I would prefer a native C++ solution and not to have to use boost or equivalent.
There is no such thing as an anonymous function in C (C++ is irrelevant here, as the function must abide by the C calling convention).
The only thing you can do is shiver access globals from the handler, probably global variables (and not constants which would be fine).
I advise making those globals thread local to avoid multithreading issues, but it is still bad in the sense that global variables make for more brittle applications.
How to ?
Note: as Luc Danton patiently explained to me, a signal may interrupt any non-atomic activity, and thus reading from a global is safe only if it is a lock-free atomic (or a few other things). Unfortunately
std::functionmay not be so, depending on your implementation, I will still leave this code to explain how it could be done providing thatstd::functionaccesses are atomic.It is possible to create a trampoline that will call stateful stuff, isolating thread and allowing re-entrant calls.
And we create the following accessor (passed to signal):
as well as the following RAII setter:
Note: both the global variable and the
handle_signalcould beprivateto theSignalSetterclass… but sincestd::signalis not…Expected usage: