#include "signalhandle.h"
|
#include <errno.h>
|
#include <mutex>
|
#include <condition_variable>
|
#include <atomic>
|
#include <map>
|
|
int CatchSignals(const int signals[], size_t count, void (* signal_handler)(int))
|
{
|
if (nullptr == signals || 0 == count || nullptr == signal_handler) {
|
return EINVAL; // Invalid argument (POSIX.1)
|
}
|
|
struct sigaction action = {0};
|
|
action.sa_handler = signal_handler;
|
action.sa_flags = 0;
|
sigemptyset(&action.sa_mask);
|
|
for (size_t i = 0; i < count; ++ i) {
|
if (0 != sigaction(signals[i], &action, nullptr)) {
|
return errno;
|
}
|
}
|
|
return 0;
|
}
|
|
int CatchSignals(const int signals[], const size_t count, SigFunc f)
|
{
|
struct _ {
|
typedef std::map<int, SigFunc> SFMap;
|
static SFMap &Funcs() { static SFMap m; return m; }
|
static void OnSig(int sig) {
|
auto pf = Funcs().find(sig);
|
if (pf != Funcs().end() && pf->second) {
|
pf->second(sig);
|
}
|
}
|
};
|
|
for (int i = 0; i < int(count); ++i) {
|
_::Funcs()[signals[i]] = f;
|
}
|
|
return CatchSignals(signals, count, &_::OnSig);
|
}
|
|
int WaitForSignals(const int signals[], const size_t count, SigFunc f)
|
{
|
std::mutex mtx;
|
std::condition_variable cv;
|
auto OnSig = [&](int sig) {
|
static std::atomic<bool> first(true);
|
if (first.exchange(false)) {
|
std::unique_lock<std::mutex> guard(mtx);
|
if (f) { f(sig); }
|
cv.notify_one();
|
}
|
};
|
|
std::unique_lock<std::mutex> guard(mtx);
|
|
const int r = CatchSignals(signals, count, OnSig);
|
if (r == 0) { // register handler.
|
cv.wait(guard);
|
}
|
return r;
|
}
|