blob: ffb1b992798973cec010a474ec0156795f75e2ac [file] [log] [blame]
#include "signal_handler.h"
#include <boost/thread/locks.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <google/gflags.h>
#include <glog/logging.h>
#include <iostream>
#include <signal.h>
#include <stdio.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <memory>
#include <queue>
#include <unistd.h>
#include "thread.h"
// Boolean signaling if the handler has been set up or not.
static bool pipe_has_been_initialized = false;
// Pipe that the signal handler writes the signal number to
static int handler_write_pipe;
// Pipe that the handler thread reads the signal number from.
static int thread_read_pipe;
// Mutex to lock the signal handler dictionary.
static boost::mutex signal_dict_lock;
// Signal handler dictionary.
static std::unique_ptr<std::map<int, boost::function<void(int)> > > signal_dict;
// Thread which reads signal numbers from the pipe and handles them.
class SignalHandlerThread: public Thread {
public:
void operator()() {
while (true) {
int signal_number;
LOG(INFO) << "Back to waiting.";
int size = read(thread_read_pipe, &signal_number, sizeof(int));
if (size == -1) {
continue;
}
CHECK_EQ(size, sizeof(int))
<< ": Read the wrong number of bytes when receiving a signal.";
LOG(INFO) << "Got signal " << signal_number;
boost::function<void(int)> function;
if (GetFromMap(*signal_dict, signal_number, &function)) {
function(signal_number);
}
}
}
};
static std::unique_ptr<SignalHandlerThread> signal_handler_thread;
static std::unique_ptr<boost::thread> signal_handler_thread_;
// Simple signal handler which writes the signal number to the pipe.
static void signal_handler(int signal_number) {
CHECK_EQ(write(handler_write_pipe, &signal_number, sizeof(int)),
sizeof(int));
}
void RegisterSignalHandler(int signal_number,
boost::function<void(int)> function){
if (!pipe_has_been_initialized) {
int pipefd[2];
CHECK(!pipe2(pipefd, 0))
<< ": Failed to create pipes for signal handler.";
thread_read_pipe = pipefd[0];
handler_write_pipe = pipefd[1];
signal_handler_thread.reset(new SignalHandlerThread());
signal_handler_thread_.reset(
new boost::thread(boost::ref(*signal_handler_thread)));
signal_dict.reset(new std::map<int, boost::function<void(int)> >());
}
struct sigaction new_action, old_action;
new_action.sa_handler = &signal_handler;
sigemptyset(&new_action.sa_mask);
boost::lock_guard<boost::mutex> lockguard(signal_dict_lock);
InsertIntoMap(signal_dict.get(), signal_number, function);
sigaction(signal_number, &new_action, NULL);
}