00001
00010 #include "sigsafe_internal.h"
00011 #ifdef _THREAD_SAFE
00012 #include <pthread.h>
00013 #endif
00014 #include <assert.h>
00015 #include <stdlib.h>
00016 #include <errno.h>
00017
00018 #ifdef _THREAD_SAFE
00019 PRIVATE_DEC(pthread_key_t sigsafe_key_) = 0;
00020 static pthread_once_t sigsafe_once = PTHREAD_ONCE_INIT;
00021 #else
00022 PRIVATE_DEC(struct sigsafe_tsd_* sigsafe_data_) = 0;
00023 static int sigsafe_inited;
00024 #endif
00025
00026 static sigsafe_user_handler_t user_handlers[SIGSAFE_SIGMAX];
00027
00028 #define SYSCALL(name, args) \
00029 PRIVATE_DEF(void sigsafe_##name##_minjmp_(void)); \
00030 PRIVATE_DEF(void sigsafe_##name##_maxjmp_(void)); \
00031 PRIVATE_DEF(void sigsafe_##name##_jmpto_ (void));
00032 #define MACH_SYSCALL(name, args) SYSCALL(name, args)
00033 #include "syscalls.h"
00034 #undef SYSCALL
00035
00036 #define SYSCALL(name, args) \
00037 { sigsafe_##name##_minjmp_, \
00038 sigsafe_##name##_maxjmp_, \
00039 sigsafe_##name##_jmpto_ },
00040 PRIVATE_DEC(struct sigsafe_syscall_ sigsafe_syscalls_[]) = {
00041 #include "syscalls.h"
00042 { NULL, NULL, NULL }
00043 };
00044 #undef SYSCALL
00045 #undef MACH_SYSCALL
00046
00047 #ifdef SIGSAFE_NO_SIGINFO
00048 static void sighandler(int signum, int code, struct sigcontext *ctx) {
00049 #else
00050 static void sighandler(int signum, siginfo_t *siginfo, ucontext_t *ctx) {
00051 #endif
00052 #ifdef _THREAD_SAFE
00053 struct sigsafe_tsd_ *sigsafe_data_ = pthread_getspecific(sigsafe_key_);
00054 #endif
00055 assert(0 < signum && signum <= SIGSAFE_SIGMAX);
00056 #ifdef SIGSAFE_DEBUG_SIGNAL
00057 write(2, "[S]", 3);
00058 #endif
00059 if (sigsafe_data_ != NULL) {
00060 if (user_handlers[signum - 1] != NULL) {
00061 #ifdef SIGSAFE_NO_SIGINFO
00062 user_handlers[signum - 1](signum, code, ctx,
00063 sigsafe_data_->user_data);
00064 #else
00065 user_handlers[signum - 1](signum, siginfo, ctx,
00066 sigsafe_data_->user_data);
00067 #endif
00068 }
00069 sigsafe_data_->signal_received = 1;
00070 sigsafe_handler_for_platform_(ctx);
00071 }
00072 }
00073
00074 #ifdef _THREAD_SAFE
00075 static void tsd_destructor(void* tsd_v) {
00076 struct sigsafe_tsd_ *sigsafe_data_ = (struct sigsafe_tsd_*) tsd_v;
00077 if (sigsafe_data_->destructor != NULL) {
00078 sigsafe_data_->destructor(sigsafe_data_->user_data);
00079 }
00080 free(sigsafe_data_);
00081 }
00082 #endif
00083
00084 static void sigsafe_init(void) {
00085
00086 volatile void *fp;
00087
00088 #ifdef _THREAD_SAFE
00089 pthread_key_create(&sigsafe_key_, &tsd_destructor);
00090 #endif
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 #ifdef _THREAD_SAFE
00101 fp = &pthread_getspecific;
00102 #endif
00103 fp = &sigsafe_handler_for_platform_;
00104 fp = &write;
00105 }
00106
00107 int sigsafe_install_handler(int signum, sigsafe_user_handler_t handler) {
00108 struct sigaction sa;
00109
00110 assert(0 < signum && signum <= SIGSAFE_SIGMAX);
00111 #ifdef _THREAD_SAFE
00112 pthread_once(&sigsafe_once, &sigsafe_init);
00113 #else
00114 if (!sigsafe_inited) {
00115 sigsafe_inited = 1;
00116 sigsafe_init();
00117 }
00118 #endif
00119 user_handlers[signum - 1] = handler;
00120 #ifdef SIGSAFE_NO_SIGINFO
00121 sa.sa_handler = (void (*)(int)) &sighandler;
00122 sa.sa_flags = SA_RESTART;
00123 #else
00124 sa.sa_sigaction = (void*) &sighandler;
00125 sa.sa_flags = SA_RESTART | SA_SIGINFO;
00126 #endif
00127
00128
00129
00130
00131 sigfillset(&sa.sa_mask);
00132
00133 if (sigaction(signum, &sa, NULL) != 0) {
00134 return -errno;
00135 }
00136 return 0;
00137 }
00138
00139 int sigsafe_install_tsd(intptr_t user_data, void (*destructor)(intptr_t)) {
00140 #ifdef _THREAD_SAFE
00141 struct sigsafe_tsd_ *sigsafe_data_ = NULL;
00142 int retval;
00143
00144 assert(pthread_getspecific(sigsafe_key_) == NULL);
00145 #else
00146 assert(sigsafe_data_ == NULL);
00147 #endif
00148
00149 sigsafe_data_ = (struct sigsafe_tsd_*) malloc(sizeof(struct sigsafe_tsd_));
00150 if (sigsafe_data_ == NULL) {
00151 return -ENOMEM;
00152 }
00153
00154 sigsafe_data_->signal_received = 0;
00155 sigsafe_data_->user_data = user_data;
00156 sigsafe_data_->destructor = destructor;
00157
00158 #ifdef _THREAD_SAFE
00159 retval = pthread_setspecific(sigsafe_key_, sigsafe_data_);
00160 if (retval != 0) {
00161 free(sigsafe_data_);
00162 return -retval;
00163 }
00164 #endif
00165
00166 return 0;
00167 }
00168
00169 intptr_t sigsafe_clear_received(void) {
00170 #ifdef _THREAD_SAFE
00171 struct sigsafe_tsd_ *sigsafe_data_;
00172
00173 sigsafe_data_ = (struct sigsafe_tsd_*) pthread_getspecific(sigsafe_key_);
00174 #endif
00175 assert(sigsafe_data_ != NULL);
00176 sigsafe_data_->signal_received = 0;
00177 return sigsafe_data_->user_data;
00178 }