src/os/solaris/vm/jsig.c

Thu, 29 May 2014 09:56:06 -0700

author
asaha
date
Thu, 29 May 2014 09:56:06 -0700
changeset 6782
f73af4455d7d
parent 2314
f95d63e2154a
child 6876
710a3c8b516e
permissions
-rw-r--r--

Merge

duke@435 1 /*
stefank@2314 2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
duke@435 25 /* CopyrightVersion 1.2 */
duke@435 26
duke@435 27 /* This is a special library that should be loaded before libc &
duke@435 28 * libthread to interpose the signal handler installation functions:
duke@435 29 * sigaction(), signal(), sigset().
duke@435 30 * Used for signal-chaining. See RFE 4381843.
duke@435 31 */
duke@435 32
duke@435 33 #include <stdlib.h>
duke@435 34 #include <stdio.h>
duke@435 35 #include <string.h>
duke@435 36 #include <signal.h>
duke@435 37 #include <dlfcn.h>
duke@435 38 #include <thread.h>
duke@435 39 #include <synch.h>
duke@435 40 #include "jvm_solaris.h"
duke@435 41
duke@435 42 #define bool int
duke@435 43 #define true 1
duke@435 44 #define false 0
duke@435 45
duke@435 46 static struct sigaction *sact = (struct sigaction *)NULL; /* saved signal handlers */
duke@435 47 static sigset_t jvmsigs;
duke@435 48
duke@435 49 /* used to synchronize the installation of signal handlers */
duke@435 50 static mutex_t mutex = DEFAULTMUTEX;
duke@435 51 static cond_t cond = DEFAULTCV;
duke@435 52 static thread_t tid = 0;
duke@435 53
duke@435 54 typedef void (*sa_handler_t)(int);
duke@435 55 typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
duke@435 56 typedef sa_handler_t (*signal_t)(int, sa_handler_t);
duke@435 57 typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *);
duke@435 58
duke@435 59 static signal_t os_signal = 0; /* os's version of signal()/sigset() */
duke@435 60 static sigaction_t os_sigaction = 0; /* os's version of sigaction() */
duke@435 61
duke@435 62 static bool jvm_signal_installing = false;
duke@435 63 static bool jvm_signal_installed = false;
duke@435 64
duke@435 65
duke@435 66 /* assume called within signal_lock */
duke@435 67 static void allocate_sact() {
duke@435 68 size_t maxsignum;
duke@435 69 maxsignum = SIGRTMAX;
duke@435 70 if (sact == NULL) {
duke@435 71 sact = (struct sigaction *)malloc((maxsignum+1) * (size_t)sizeof(struct sigaction));
duke@435 72 memset(sact, 0, (maxsignum+1) * (size_t)sizeof(struct sigaction));
duke@435 73 }
duke@435 74
duke@435 75 if (sact == NULL) {
duke@435 76 printf("%s\n", "libjsig.so unable to allocate memory");
duke@435 77 exit(0);
duke@435 78 }
duke@435 79
duke@435 80 sigemptyset(&jvmsigs);
duke@435 81 }
duke@435 82
duke@435 83 static void signal_lock() {
duke@435 84 mutex_lock(&mutex);
duke@435 85 /* When the jvm is installing its set of signal handlers, threads
duke@435 86 * other than the jvm thread should wait */
duke@435 87 if (jvm_signal_installing) {
duke@435 88 if (tid != thr_self()) {
duke@435 89 cond_wait(&cond, &mutex);
duke@435 90 }
duke@435 91 }
duke@435 92 }
duke@435 93
duke@435 94 static void signal_unlock() {
duke@435 95 mutex_unlock(&mutex);
duke@435 96 }
duke@435 97
duke@435 98 static sa_handler_t call_os_signal(int sig, sa_handler_t disp,
duke@435 99 bool is_sigset) {
duke@435 100 if (os_signal == NULL) {
duke@435 101 if (!is_sigset) {
duke@435 102 os_signal = (signal_t)dlsym(RTLD_NEXT, "signal");
duke@435 103 } else {
duke@435 104 os_signal = (signal_t)dlsym(RTLD_NEXT, "sigset");
duke@435 105 }
duke@435 106 if (os_signal == NULL) {
duke@435 107 printf("%s\n", dlerror());
duke@435 108 exit(0);
duke@435 109 }
duke@435 110 }
duke@435 111 return (*os_signal)(sig, disp);
duke@435 112 }
duke@435 113
duke@435 114 static void save_signal_handler(int sig, sa_handler_t disp, bool is_sigset) {
duke@435 115 sigset_t set;
duke@435 116 if (sact == NULL) {
duke@435 117 allocate_sact();
duke@435 118 }
duke@435 119 sact[sig].sa_handler = disp;
duke@435 120 sigemptyset(&set);
duke@435 121 sact[sig].sa_mask = set;
duke@435 122 if (!is_sigset) {
duke@435 123 sact[sig].sa_flags = SA_NODEFER;
duke@435 124 if (sig != SIGILL && sig != SIGTRAP && sig != SIGPWR) {
duke@435 125 sact[sig].sa_flags |= SA_RESETHAND;
duke@435 126 }
duke@435 127 } else {
duke@435 128 sact[sig].sa_flags = 0;
duke@435 129 }
duke@435 130 }
duke@435 131
duke@435 132 static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
duke@435 133 sa_handler_t oldhandler;
duke@435 134 bool sigblocked;
duke@435 135
duke@435 136 signal_lock();
duke@435 137 if (sact == NULL) {
duke@435 138 allocate_sact();
duke@435 139 }
duke@435 140
duke@435 141 if (jvm_signal_installed && sigismember(&jvmsigs, sig)) {
duke@435 142 /* jvm has installed its signal handler for this signal. */
duke@435 143 /* Save the handler. Don't really install it. */
duke@435 144 if (is_sigset) {
duke@435 145 /* We won't honor the SIG_HOLD request to change the signal mask */
duke@435 146 sigblocked = sigismember(&(sact[sig].sa_mask), sig);
duke@435 147 }
duke@435 148 oldhandler = sact[sig].sa_handler;
duke@435 149 save_signal_handler(sig, disp, is_sigset);
duke@435 150
duke@435 151 if (is_sigset && sigblocked) {
duke@435 152 oldhandler = SIG_HOLD;
duke@435 153 }
duke@435 154
duke@435 155 signal_unlock();
duke@435 156 return oldhandler;
duke@435 157 } else if (jvm_signal_installing) {
duke@435 158 /* jvm is installing its signal handlers. Install the new
duke@435 159 * handlers and save the old ones. jvm uses sigaction().
duke@435 160 * Leave the piece here just in case. */
duke@435 161 oldhandler = call_os_signal(sig, disp, is_sigset);
duke@435 162 save_signal_handler(sig, oldhandler, is_sigset);
duke@435 163
duke@435 164 /* Record the signals used by jvm */
duke@435 165 sigaddset(&jvmsigs, sig);
duke@435 166
duke@435 167 signal_unlock();
duke@435 168 return oldhandler;
duke@435 169 } else {
duke@435 170 /* jvm has no relation with this signal (yet). Install the
duke@435 171 * the handler. */
duke@435 172 oldhandler = call_os_signal(sig, disp, is_sigset);
duke@435 173
duke@435 174 signal_unlock();
duke@435 175 return oldhandler;
duke@435 176 }
duke@435 177 }
duke@435 178
duke@435 179 sa_handler_t signal(int sig, sa_handler_t disp) {
duke@435 180 return set_signal(sig, disp, false);
duke@435 181 }
duke@435 182
duke@435 183 sa_handler_t sigset(int sig, sa_handler_t disp) {
duke@435 184 return set_signal(sig, disp, true);
duke@435 185 }
duke@435 186
duke@435 187 static int call_os_sigaction(int sig, const struct sigaction *act,
duke@435 188 struct sigaction *oact) {
duke@435 189 if (os_sigaction == NULL) {
duke@435 190 os_sigaction = (sigaction_t)dlsym(RTLD_NEXT, "sigaction");
duke@435 191 if (os_sigaction == NULL) {
duke@435 192 printf("%s\n", dlerror());
duke@435 193 exit(0);
duke@435 194 }
duke@435 195 }
duke@435 196 return (*os_sigaction)(sig, act, oact);
duke@435 197 }
duke@435 198
duke@435 199 int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
duke@435 200 int res;
duke@435 201 struct sigaction oldAct;
duke@435 202
duke@435 203 signal_lock();
duke@435 204
duke@435 205 if (sact == NULL ) {
duke@435 206 allocate_sact();
duke@435 207 }
duke@435 208 if (jvm_signal_installed && sigismember(&jvmsigs, sig)) {
duke@435 209 /* jvm has installed its signal handler for this signal. */
duke@435 210 /* Save the handler. Don't really install it. */
duke@435 211 if (oact != NULL) {
duke@435 212 *oact = sact[sig];
duke@435 213 }
duke@435 214 if (act != NULL) {
duke@435 215 sact[sig] = *act;
duke@435 216 }
duke@435 217
duke@435 218 signal_unlock();
duke@435 219 return 0;
duke@435 220 } else if (jvm_signal_installing) {
duke@435 221 /* jvm is installing its signal handlers. Install the new
duke@435 222 * handlers and save the old ones. */
duke@435 223 res = call_os_sigaction(sig, act, &oldAct);
duke@435 224 sact[sig] = oldAct;
duke@435 225 if (oact != NULL) {
duke@435 226 *oact = oldAct;
duke@435 227 }
duke@435 228
duke@435 229 /* Record the signals used by jvm */
duke@435 230 sigaddset(&jvmsigs, sig);
duke@435 231
duke@435 232 signal_unlock();
duke@435 233 return res;
duke@435 234 } else {
duke@435 235 /* jvm has no relation with this signal (yet). Install the
duke@435 236 * the handler. */
duke@435 237 res = call_os_sigaction(sig, act, oact);
duke@435 238
duke@435 239 signal_unlock();
duke@435 240 return res;
duke@435 241 }
duke@435 242 }
duke@435 243
duke@435 244 /* The four functions for the jvm to call into */
duke@435 245 void JVM_begin_signal_setting() {
duke@435 246 signal_lock();
duke@435 247 jvm_signal_installing = true;
duke@435 248 tid = thr_self();
duke@435 249 signal_unlock();
duke@435 250 }
duke@435 251
duke@435 252 void JVM_end_signal_setting() {
duke@435 253 signal_lock();
duke@435 254 jvm_signal_installed = true;
duke@435 255 jvm_signal_installing = false;
duke@435 256 cond_broadcast(&cond);
duke@435 257 signal_unlock();
duke@435 258 }
duke@435 259
duke@435 260 struct sigaction *JVM_get_signal_action(int sig) {
duke@435 261 if (sact == NULL) {
duke@435 262 allocate_sact();
duke@435 263 }
duke@435 264 /* Does race condition make sense here? */
duke@435 265 if (sigismember(&jvmsigs, sig)) {
duke@435 266 return &sact[sig];
duke@435 267 }
duke@435 268 return NULL;
duke@435 269 }
duke@435 270
duke@435 271 int JVM_get_libjsig_version() {
duke@435 272 return JSIG_VERSION_1_4_1;
duke@435 273 }

mercurial