src/os/linux/vm/jsig.c

Thu, 13 Mar 2014 14:57:01 -0700

author
kvn
date
Thu, 13 Mar 2014 14:57:01 -0700
changeset 6513
bbfbe9b06038
parent 5420
732af649bc3a
child 6876
710a3c8b516e
permissions
-rw-r--r--

Merge

duke@435 1 /*
ccheung@5420 2 * Copyright (c) 2001, 2013, 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 <signal.h>
duke@435 34 #include <dlfcn.h>
duke@435 35 #include <pthread.h>
duke@435 36 #include <stdio.h>
duke@435 37 #include <stdlib.h>
duke@435 38
duke@435 39 #define bool int
duke@435 40 #define true 1
duke@435 41 #define false 0
duke@435 42
duke@435 43 #define MAXSIGNUM 32
duke@435 44 #define MASK(sig) ((unsigned int)1 << sig)
duke@435 45
duke@435 46 static struct sigaction sact[MAXSIGNUM]; /* saved signal handlers */
duke@435 47 static unsigned int jvmsigs = 0; /* signals used by jvm */
duke@435 48
duke@435 49 /* used to synchronize the installation of signal handlers */
duke@435 50 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
duke@435 51 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
duke@435 52 static pthread_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 static void signal_lock() {
duke@435 66 pthread_mutex_lock(&mutex);
duke@435 67 /* When the jvm is installing its set of signal handlers, threads
duke@435 68 * other than the jvm thread should wait */
duke@435 69 if (jvm_signal_installing) {
duke@435 70 if (tid != pthread_self()) {
duke@435 71 pthread_cond_wait(&cond, &mutex);
duke@435 72 }
duke@435 73 }
duke@435 74 }
duke@435 75
duke@435 76 static void signal_unlock() {
duke@435 77 pthread_mutex_unlock(&mutex);
duke@435 78 }
duke@435 79
duke@435 80 static sa_handler_t call_os_signal(int sig, sa_handler_t disp,
duke@435 81 bool is_sigset) {
duke@435 82 if (os_signal == NULL) {
duke@435 83 if (!is_sigset) {
duke@435 84 os_signal = (signal_t)dlsym(RTLD_NEXT, "signal");
duke@435 85 } else {
duke@435 86 os_signal = (signal_t)dlsym(RTLD_NEXT, "sigset");
duke@435 87 }
duke@435 88 if (os_signal == NULL) {
duke@435 89 printf("%s\n", dlerror());
duke@435 90 exit(0);
duke@435 91 }
duke@435 92 }
duke@435 93 return (*os_signal)(sig, disp);
duke@435 94 }
duke@435 95
duke@435 96 static void save_signal_handler(int sig, sa_handler_t disp) {
duke@435 97 sigset_t set;
duke@435 98 sact[sig].sa_handler = disp;
duke@435 99 sigemptyset(&set);
duke@435 100 sact[sig].sa_mask = set;
duke@435 101 sact[sig].sa_flags = 0;
duke@435 102 }
duke@435 103
duke@435 104 static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
duke@435 105 sa_handler_t oldhandler;
duke@435 106 bool sigused;
duke@435 107
duke@435 108 signal_lock();
duke@435 109
ccheung@5420 110 sigused = (sig < MAXSIGNUM) && ((MASK(sig) & jvmsigs) != 0);
duke@435 111 if (jvm_signal_installed && sigused) {
duke@435 112 /* jvm has installed its signal handler for this signal. */
duke@435 113 /* Save the handler. Don't really install it. */
duke@435 114 oldhandler = sact[sig].sa_handler;
duke@435 115 save_signal_handler(sig, disp);
duke@435 116
duke@435 117 signal_unlock();
duke@435 118 return oldhandler;
ccheung@5420 119 } else if (sig < MAXSIGNUM && jvm_signal_installing) {
duke@435 120 /* jvm is installing its signal handlers. Install the new
duke@435 121 * handlers and save the old ones. jvm uses sigaction().
duke@435 122 * Leave the piece here just in case. */
duke@435 123 oldhandler = call_os_signal(sig, disp, is_sigset);
duke@435 124 save_signal_handler(sig, oldhandler);
duke@435 125
duke@435 126 /* Record the signals used by jvm */
duke@435 127 jvmsigs |= MASK(sig);
duke@435 128
duke@435 129 signal_unlock();
duke@435 130 return oldhandler;
duke@435 131 } else {
duke@435 132 /* jvm has no relation with this signal (yet). Install the
duke@435 133 * the handler. */
duke@435 134 oldhandler = call_os_signal(sig, disp, is_sigset);
duke@435 135
duke@435 136 signal_unlock();
duke@435 137 return oldhandler;
duke@435 138 }
duke@435 139 }
duke@435 140
duke@435 141 sa_handler_t signal(int sig, sa_handler_t disp) {
duke@435 142 return set_signal(sig, disp, false);
duke@435 143 }
duke@435 144
duke@435 145 sa_handler_t sigset(int sig, sa_handler_t disp) {
duke@435 146 return set_signal(sig, disp, true);
duke@435 147 }
duke@435 148
duke@435 149 static int call_os_sigaction(int sig, const struct sigaction *act,
duke@435 150 struct sigaction *oact) {
duke@435 151 if (os_sigaction == NULL) {
duke@435 152 os_sigaction = (sigaction_t)dlsym(RTLD_NEXT, "sigaction");
duke@435 153 if (os_sigaction == NULL) {
duke@435 154 printf("%s\n", dlerror());
duke@435 155 exit(0);
duke@435 156 }
duke@435 157 }
duke@435 158 return (*os_sigaction)(sig, act, oact);
duke@435 159 }
duke@435 160
duke@435 161 int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
duke@435 162 int res;
duke@435 163 bool sigused;
duke@435 164 struct sigaction oldAct;
duke@435 165
duke@435 166 signal_lock();
duke@435 167
ccheung@5420 168 sigused = (sig < MAXSIGNUM) && ((MASK(sig) & jvmsigs) != 0);
duke@435 169 if (jvm_signal_installed && sigused) {
duke@435 170 /* jvm has installed its signal handler for this signal. */
duke@435 171 /* Save the handler. Don't really install it. */
duke@435 172 if (oact != NULL) {
duke@435 173 *oact = sact[sig];
duke@435 174 }
duke@435 175 if (act != NULL) {
duke@435 176 sact[sig] = *act;
duke@435 177 }
duke@435 178
duke@435 179 signal_unlock();
duke@435 180 return 0;
ccheung@5420 181 } else if (sig < MAXSIGNUM && jvm_signal_installing) {
duke@435 182 /* jvm is installing its signal handlers. Install the new
duke@435 183 * handlers and save the old ones. */
duke@435 184 res = call_os_sigaction(sig, act, &oldAct);
duke@435 185 sact[sig] = oldAct;
duke@435 186 if (oact != NULL) {
duke@435 187 *oact = oldAct;
duke@435 188 }
duke@435 189
duke@435 190 /* Record the signals used by jvm */
duke@435 191 jvmsigs |= MASK(sig);
duke@435 192
duke@435 193 signal_unlock();
duke@435 194 return res;
duke@435 195 } else {
duke@435 196 /* jvm has no relation with this signal (yet). Install the
duke@435 197 * the handler. */
duke@435 198 res = call_os_sigaction(sig, act, oact);
duke@435 199
duke@435 200 signal_unlock();
duke@435 201 return res;
duke@435 202 }
duke@435 203 }
duke@435 204
duke@435 205 /* The three functions for the jvm to call into */
duke@435 206 void JVM_begin_signal_setting() {
duke@435 207 signal_lock();
duke@435 208 jvm_signal_installing = true;
duke@435 209 tid = pthread_self();
duke@435 210 signal_unlock();
duke@435 211 }
duke@435 212
duke@435 213 void JVM_end_signal_setting() {
duke@435 214 signal_lock();
duke@435 215 jvm_signal_installed = true;
duke@435 216 jvm_signal_installing = false;
duke@435 217 pthread_cond_broadcast(&cond);
duke@435 218 signal_unlock();
duke@435 219 }
duke@435 220
duke@435 221 struct sigaction *JVM_get_signal_action(int sig) {
duke@435 222 /* Does race condition make sense here? */
duke@435 223 if ((MASK(sig) & jvmsigs) != 0) {
duke@435 224 return &sact[sig];
duke@435 225 }
duke@435 226 return NULL;
duke@435 227 }

mercurial