blob: ffb1b992798973cec010a474ec0156795f75e2ac [file] [log] [blame]
Austin Schuh9b360e92013-03-27 04:47:04 +00001#include "signal_handler.h"
2
3#include <boost/thread/locks.hpp>
4#include <boost/thread.hpp>
5#include <boost/bind.hpp>
6#include <boost/function.hpp>
7#include <google/gflags.h>
8#include <glog/logging.h>
9#include <iostream>
10#include <signal.h>
11#include <stdio.h>
12#include <sys/socket.h>
13#include <linux/can.h>
14#include <memory>
15#include <queue>
16#include <unistd.h>
17
18#include "thread.h"
19
20// Boolean signaling if the handler has been set up or not.
21static bool pipe_has_been_initialized = false;
22
23// Pipe that the signal handler writes the signal number to
24static int handler_write_pipe;
25// Pipe that the handler thread reads the signal number from.
26static int thread_read_pipe;
27// Mutex to lock the signal handler dictionary.
28static boost::mutex signal_dict_lock;
29// Signal handler dictionary.
30static std::unique_ptr<std::map<int, boost::function<void(int)> > > signal_dict;
31
32// Thread which reads signal numbers from the pipe and handles them.
33class SignalHandlerThread: public Thread {
34 public:
35 void operator()() {
36 while (true) {
37 int signal_number;
38 LOG(INFO) << "Back to waiting.";
39 int size = read(thread_read_pipe, &signal_number, sizeof(int));
40 if (size == -1) {
41 continue;
42 }
43 CHECK_EQ(size, sizeof(int))
44 << ": Read the wrong number of bytes when receiving a signal.";
45 LOG(INFO) << "Got signal " << signal_number;
46
47 boost::function<void(int)> function;
48 if (GetFromMap(*signal_dict, signal_number, &function)) {
49 function(signal_number);
50 }
51 }
52 }
53};
54
55static std::unique_ptr<SignalHandlerThread> signal_handler_thread;
56static std::unique_ptr<boost::thread> signal_handler_thread_;
57
58// Simple signal handler which writes the signal number to the pipe.
59static void signal_handler(int signal_number) {
60 CHECK_EQ(write(handler_write_pipe, &signal_number, sizeof(int)),
61 sizeof(int));
62}
63
64void RegisterSignalHandler(int signal_number,
65 boost::function<void(int)> function){
66 if (!pipe_has_been_initialized) {
67 int pipefd[2];
68 CHECK(!pipe2(pipefd, 0))
69 << ": Failed to create pipes for signal handler.";
70 thread_read_pipe = pipefd[0];
71 handler_write_pipe = pipefd[1];
72 signal_handler_thread.reset(new SignalHandlerThread());
73 signal_handler_thread_.reset(
74 new boost::thread(boost::ref(*signal_handler_thread)));
75 signal_dict.reset(new std::map<int, boost::function<void(int)> >());
76 }
77 struct sigaction new_action, old_action;
78
79 new_action.sa_handler = &signal_handler;
80 sigemptyset(&new_action.sa_mask);
81
82 boost::lock_guard<boost::mutex> lockguard(signal_dict_lock);
83
84 InsertIntoMap(signal_dict.get(), signal_number, function);
85
86 sigaction(signal_number, &new_action, NULL);
87}