File: UnixSignalInterposer.cpp

package info (click to toggle)
tulip 3.7.0dfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 39,428 kB
  • sloc: cpp: 231,403; php: 11,023; python: 1,128; sh: 671; yacc: 522; makefile: 315; xml: 63; lex: 55
file content (145 lines) | stat: -rwxr-xr-x 4,591 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/**
 *
 * This file is part of Tulip (www.tulip-software.org)
 *
 * Authors: David Auber and the Tulip development Team
 * from LaBRI, University of Bordeaux 1 and Inria Bordeaux - Sud Ouest
 *
 * Tulip is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 3
 * of the License, or (at your option) any later version.
 *
 * Tulip is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 */

// This file has to be compiled on Unix hosts into a shared library
// or has to be linked statically against an executable/shared library.
// It allows to override the following system functions : sigaction, signal and sigset.
// The purpose is to prevent custom signal handlers being overwritten by libraries
// linked against the application (e.g. graphics driver).
// When compiled as a shared library the environment variable LD_PRELOAD (DYLD_INSERT_LIBRARIES on MacOS)
// has to be filled with the path to the resulting shared library before launching the application.
// For instance : $ LD_PRELOAD=<path to the compiled shared library> <path_to_application_executable> <args>

#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <set>

#include <unistd.h>
#include <dlfcn.h>

#include "UnixSignalInterposer.h"

using namespace std;

// some typedef on function pointers
typedef SignalHandlerFunc* SignalFunc(int, SignalHandlerFunc*);
typedef int SigactionFunc(int, const struct sigaction *, struct sigaction *);

static SigactionFunc *real_sigaction = NULL;
static SignalFunc *real_signal = NULL;
static SignalFunc *real_sigset = NULL;

static set<int> handledSignals;

#ifndef __THROW
#define __THROW
#endif

template <typename TO, typename FROM> TO nasty_cast(FROM f) {
  union {
    FROM f;
    TO t;
  } u;
  u.f = f;
  return u.t;
}

// this function will be called when the library is loaded
static void initSignalInterposer(void) __attribute__((constructor));

static void initSignalInterposer(void) {
  real_sigaction = nasty_cast<SigactionFunc *>(dlsym(RTLD_NEXT, "sigaction"));
  real_signal = nasty_cast<SignalFunc *>(dlsym(RTLD_NEXT, "signal"));
  real_sigset = nasty_cast<SignalFunc *>(dlsym(RTLD_NEXT, "sigset"));
}

void installSignalHandler(int sig, SignalHandlerFunc *handler) {

  handledSignals.insert(sig);

  // custom signal handler is installed for the signals in the vector
  struct sigaction action;
  sigemptyset(&action.sa_mask);
  action.sa_handler = handler;

  real_sigaction(sig, &action, NULL);

}

void installSignalHandler(int sig, SigactionHandlerFunc *handler) {

  // fill this vector according to the signals you want to handle
  handledSignals.insert(sig);

  // custom signal handler is installed for the signals in the vector
  struct sigaction action;
  sigemptyset(&action.sa_mask);
  action.sa_flags = SA_RESTART | SA_SIGINFO;
  action.sa_sigaction = handler;

  real_sigaction(sig, &action, NULL);

}

// redefinition of the signal function
// if the signal passed as first parameter is already treated by our custom handler,
// do nothing and return SIG_DFL
// if the signal is not treated by our custom handler, call the real signal function
SignalHandlerFunc *signal (int sig, SignalHandlerFunc *handler) __THROW {

  if (handledSignals.find(sig) != handledSignals.end()) {
    return SIG_DFL;
  }
  else {
    return real_signal(sig, handler);
  }

}

// redefinition of the sigset function
// if the signal passed as first parameter is already treated by our custom handler,
// do nothing and return SIG_DFL
// if the signal is not treated by our custom handler, call the real sigset function
SignalHandlerFunc *sigset(int sig, SignalHandlerFunc *handler) __THROW {

  if(handledSignals.find(sig) != handledSignals.end()) {
    return SIG_DFL;
  }
  else {
    return real_sigset(sig, handler);
  }

}

// redefinition of the sigaction function
// if the signal passed as first parameter is already treated by our custom handler,
// do nothing and return 0
// if the signal is not treated by our custom handler, call the real sigaction function
int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) __THROW {

  if (std::find(handledSignals.begin(), handledSignals.end(), sig) != handledSignals.end()) {
    return 0;
  }
  else {
    return real_sigaction(sig, act, oact);
  }

}