Skip to content

Instantly share code, notes, and snippets.

@eruffaldi
Last active December 22, 2023 23:00
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eruffaldi/c8d44324cfa0e2fd4fdc to your computer and use it in GitHub Desktop.
Save eruffaldi/c8d44324cfa0e2fd4fdc to your computer and use it in GitHub Desktop.
Signal as Lambda Functions in C++
#include <functional>
#include <fstream>
#include <iostream>
#include <signal.h>
/// one holder per signal type
template <int q>
struct Signal
{
using sfx = void(int );
typedef std::function<void(int )> fx_t;
fx_t fx;
static Signal holder;
static void handler(int sn) { holder.fx(sn); }
};
template <int q> Signal<q> Signal<q>::holder;
// this is a scope
template <int q>
struct SignalScope
{
using sfx = void(int);
sfx *oldfx_;
SignalScope(typename Signal<q>::fx_t fx)
{
Signal<q>::holder.fx = fx;
oldfx_ = signal(q,&Signal<q>::handler);
}
~SignalScope()
{
signal(q,oldfx_);
}
};
int main(int argc, char** argv)
{
std::ofstream onf(argv[1]);
if(!onf)
return 0;
SignalScope<SIGINT> scope([&onf](int signum) {
std::cerr << "catched!" << std::endl;
onf.close();
exit(0);
});
int i = 0;
while(1)
{
// ... do task ... write and ensure things
std::cout << i << std::endl;
onf << i << '\n';
i++;
}
}
@dfreese
Copy link

dfreese commented Sep 25, 2020

This was an interesting example. Thanks for putting it up. It looks like using multiple SignalScope objects could cause problems, as the Signal<q>::holder.fx is not replaced when the signal handler is replaced.

SignalScope<SIGINT> scope([](int val) {});
{
    int signal_val = -1;
    SignalScope<SIGINT> inner_scope([&signal_val](int val) { signal_val = val; });
}
// inner_scope has been destructed, but Signal<SIGINT>::holder.fx still points at
// the lambda passed to inner_scope, which will write to invalid memory in this case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment