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);
}
}
|