annotate src/os/linux/vm/jsig.c @ 9010:08a16c26907f

MX_TESTFILE environment variable can be used to specify (and preserve) the test list file used by 'mx unittest'. This is useful when wanting to run the command under gdb.
author Doug Simon <doug.simon@oracle.com>
date Thu, 11 Apr 2013 21:40:52 +0200
parents f95d63e2154a
children 732af649bc3a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 /* CopyrightVersion 1.2 */
a61af66fc99e Initial load
duke
parents:
diff changeset
26
a61af66fc99e Initial load
duke
parents:
diff changeset
27 /* This is a special library that should be loaded before libc &
a61af66fc99e Initial load
duke
parents:
diff changeset
28 * libthread to interpose the signal handler installation functions:
a61af66fc99e Initial load
duke
parents:
diff changeset
29 * sigaction(), signal(), sigset().
a61af66fc99e Initial load
duke
parents:
diff changeset
30 * Used for signal-chaining. See RFE 4381843.
a61af66fc99e Initial load
duke
parents:
diff changeset
31 */
a61af66fc99e Initial load
duke
parents:
diff changeset
32
a61af66fc99e Initial load
duke
parents:
diff changeset
33 #include <signal.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
34 #include <dlfcn.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
35 #include <pthread.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
36 #include <stdio.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
37 #include <stdlib.h>
a61af66fc99e Initial load
duke
parents:
diff changeset
38
a61af66fc99e Initial load
duke
parents:
diff changeset
39 #define bool int
a61af66fc99e Initial load
duke
parents:
diff changeset
40 #define true 1
a61af66fc99e Initial load
duke
parents:
diff changeset
41 #define false 0
a61af66fc99e Initial load
duke
parents:
diff changeset
42
a61af66fc99e Initial load
duke
parents:
diff changeset
43 #define MAXSIGNUM 32
a61af66fc99e Initial load
duke
parents:
diff changeset
44 #define MASK(sig) ((unsigned int)1 << sig)
a61af66fc99e Initial load
duke
parents:
diff changeset
45
a61af66fc99e Initial load
duke
parents:
diff changeset
46 static struct sigaction sact[MAXSIGNUM]; /* saved signal handlers */
a61af66fc99e Initial load
duke
parents:
diff changeset
47 static unsigned int jvmsigs = 0; /* signals used by jvm */
a61af66fc99e Initial load
duke
parents:
diff changeset
48
a61af66fc99e Initial load
duke
parents:
diff changeset
49 /* used to synchronize the installation of signal handlers */
a61af66fc99e Initial load
duke
parents:
diff changeset
50 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
a61af66fc99e Initial load
duke
parents:
diff changeset
51 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
a61af66fc99e Initial load
duke
parents:
diff changeset
52 static pthread_t tid = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
53
a61af66fc99e Initial load
duke
parents:
diff changeset
54 typedef void (*sa_handler_t)(int);
a61af66fc99e Initial load
duke
parents:
diff changeset
55 typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
a61af66fc99e Initial load
duke
parents:
diff changeset
56 typedef sa_handler_t (*signal_t)(int, sa_handler_t);
a61af66fc99e Initial load
duke
parents:
diff changeset
57 typedef int (*sigaction_t)(int, const struct sigaction *, struct sigaction *);
a61af66fc99e Initial load
duke
parents:
diff changeset
58
a61af66fc99e Initial load
duke
parents:
diff changeset
59 static signal_t os_signal = 0; /* os's version of signal()/sigset() */
a61af66fc99e Initial load
duke
parents:
diff changeset
60 static sigaction_t os_sigaction = 0; /* os's version of sigaction() */
a61af66fc99e Initial load
duke
parents:
diff changeset
61
a61af66fc99e Initial load
duke
parents:
diff changeset
62 static bool jvm_signal_installing = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
63 static bool jvm_signal_installed = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
64
a61af66fc99e Initial load
duke
parents:
diff changeset
65 static void signal_lock() {
a61af66fc99e Initial load
duke
parents:
diff changeset
66 pthread_mutex_lock(&mutex);
a61af66fc99e Initial load
duke
parents:
diff changeset
67 /* When the jvm is installing its set of signal handlers, threads
a61af66fc99e Initial load
duke
parents:
diff changeset
68 * other than the jvm thread should wait */
a61af66fc99e Initial load
duke
parents:
diff changeset
69 if (jvm_signal_installing) {
a61af66fc99e Initial load
duke
parents:
diff changeset
70 if (tid != pthread_self()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
71 pthread_cond_wait(&cond, &mutex);
a61af66fc99e Initial load
duke
parents:
diff changeset
72 }
a61af66fc99e Initial load
duke
parents:
diff changeset
73 }
a61af66fc99e Initial load
duke
parents:
diff changeset
74 }
a61af66fc99e Initial load
duke
parents:
diff changeset
75
a61af66fc99e Initial load
duke
parents:
diff changeset
76 static void signal_unlock() {
a61af66fc99e Initial load
duke
parents:
diff changeset
77 pthread_mutex_unlock(&mutex);
a61af66fc99e Initial load
duke
parents:
diff changeset
78 }
a61af66fc99e Initial load
duke
parents:
diff changeset
79
a61af66fc99e Initial load
duke
parents:
diff changeset
80 static sa_handler_t call_os_signal(int sig, sa_handler_t disp,
a61af66fc99e Initial load
duke
parents:
diff changeset
81 bool is_sigset) {
a61af66fc99e Initial load
duke
parents:
diff changeset
82 if (os_signal == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
83 if (!is_sigset) {
a61af66fc99e Initial load
duke
parents:
diff changeset
84 os_signal = (signal_t)dlsym(RTLD_NEXT, "signal");
a61af66fc99e Initial load
duke
parents:
diff changeset
85 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
86 os_signal = (signal_t)dlsym(RTLD_NEXT, "sigset");
a61af66fc99e Initial load
duke
parents:
diff changeset
87 }
a61af66fc99e Initial load
duke
parents:
diff changeset
88 if (os_signal == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
89 printf("%s\n", dlerror());
a61af66fc99e Initial load
duke
parents:
diff changeset
90 exit(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
91 }
a61af66fc99e Initial load
duke
parents:
diff changeset
92 }
a61af66fc99e Initial load
duke
parents:
diff changeset
93 return (*os_signal)(sig, disp);
a61af66fc99e Initial load
duke
parents:
diff changeset
94 }
a61af66fc99e Initial load
duke
parents:
diff changeset
95
a61af66fc99e Initial load
duke
parents:
diff changeset
96 static void save_signal_handler(int sig, sa_handler_t disp) {
a61af66fc99e Initial load
duke
parents:
diff changeset
97 sigset_t set;
a61af66fc99e Initial load
duke
parents:
diff changeset
98 sact[sig].sa_handler = disp;
a61af66fc99e Initial load
duke
parents:
diff changeset
99 sigemptyset(&set);
a61af66fc99e Initial load
duke
parents:
diff changeset
100 sact[sig].sa_mask = set;
a61af66fc99e Initial load
duke
parents:
diff changeset
101 sact[sig].sa_flags = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
102 }
a61af66fc99e Initial load
duke
parents:
diff changeset
103
a61af66fc99e Initial load
duke
parents:
diff changeset
104 static sa_handler_t set_signal(int sig, sa_handler_t disp, bool is_sigset) {
a61af66fc99e Initial load
duke
parents:
diff changeset
105 sa_handler_t oldhandler;
a61af66fc99e Initial load
duke
parents:
diff changeset
106 bool sigused;
a61af66fc99e Initial load
duke
parents:
diff changeset
107
a61af66fc99e Initial load
duke
parents:
diff changeset
108 signal_lock();
a61af66fc99e Initial load
duke
parents:
diff changeset
109
a61af66fc99e Initial load
duke
parents:
diff changeset
110 sigused = (MASK(sig) & jvmsigs) != 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
111 if (jvm_signal_installed && sigused) {
a61af66fc99e Initial load
duke
parents:
diff changeset
112 /* jvm has installed its signal handler for this signal. */
a61af66fc99e Initial load
duke
parents:
diff changeset
113 /* Save the handler. Don't really install it. */
a61af66fc99e Initial load
duke
parents:
diff changeset
114 oldhandler = sact[sig].sa_handler;
a61af66fc99e Initial load
duke
parents:
diff changeset
115 save_signal_handler(sig, disp);
a61af66fc99e Initial load
duke
parents:
diff changeset
116
a61af66fc99e Initial load
duke
parents:
diff changeset
117 signal_unlock();
a61af66fc99e Initial load
duke
parents:
diff changeset
118 return oldhandler;
a61af66fc99e Initial load
duke
parents:
diff changeset
119 } else if (jvm_signal_installing) {
a61af66fc99e Initial load
duke
parents:
diff changeset
120 /* jvm is installing its signal handlers. Install the new
a61af66fc99e Initial load
duke
parents:
diff changeset
121 * handlers and save the old ones. jvm uses sigaction().
a61af66fc99e Initial load
duke
parents:
diff changeset
122 * Leave the piece here just in case. */
a61af66fc99e Initial load
duke
parents:
diff changeset
123 oldhandler = call_os_signal(sig, disp, is_sigset);
a61af66fc99e Initial load
duke
parents:
diff changeset
124 save_signal_handler(sig, oldhandler);
a61af66fc99e Initial load
duke
parents:
diff changeset
125
a61af66fc99e Initial load
duke
parents:
diff changeset
126 /* Record the signals used by jvm */
a61af66fc99e Initial load
duke
parents:
diff changeset
127 jvmsigs |= MASK(sig);
a61af66fc99e Initial load
duke
parents:
diff changeset
128
a61af66fc99e Initial load
duke
parents:
diff changeset
129 signal_unlock();
a61af66fc99e Initial load
duke
parents:
diff changeset
130 return oldhandler;
a61af66fc99e Initial load
duke
parents:
diff changeset
131 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
132 /* jvm has no relation with this signal (yet). Install the
a61af66fc99e Initial load
duke
parents:
diff changeset
133 * the handler. */
a61af66fc99e Initial load
duke
parents:
diff changeset
134 oldhandler = call_os_signal(sig, disp, is_sigset);
a61af66fc99e Initial load
duke
parents:
diff changeset
135
a61af66fc99e Initial load
duke
parents:
diff changeset
136 signal_unlock();
a61af66fc99e Initial load
duke
parents:
diff changeset
137 return oldhandler;
a61af66fc99e Initial load
duke
parents:
diff changeset
138 }
a61af66fc99e Initial load
duke
parents:
diff changeset
139 }
a61af66fc99e Initial load
duke
parents:
diff changeset
140
a61af66fc99e Initial load
duke
parents:
diff changeset
141 sa_handler_t signal(int sig, sa_handler_t disp) {
a61af66fc99e Initial load
duke
parents:
diff changeset
142 return set_signal(sig, disp, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
143 }
a61af66fc99e Initial load
duke
parents:
diff changeset
144
a61af66fc99e Initial load
duke
parents:
diff changeset
145 sa_handler_t sigset(int sig, sa_handler_t disp) {
a61af66fc99e Initial load
duke
parents:
diff changeset
146 return set_signal(sig, disp, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
147 }
a61af66fc99e Initial load
duke
parents:
diff changeset
148
a61af66fc99e Initial load
duke
parents:
diff changeset
149 static int call_os_sigaction(int sig, const struct sigaction *act,
a61af66fc99e Initial load
duke
parents:
diff changeset
150 struct sigaction *oact) {
a61af66fc99e Initial load
duke
parents:
diff changeset
151 if (os_sigaction == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
152 os_sigaction = (sigaction_t)dlsym(RTLD_NEXT, "sigaction");
a61af66fc99e Initial load
duke
parents:
diff changeset
153 if (os_sigaction == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
154 printf("%s\n", dlerror());
a61af66fc99e Initial load
duke
parents:
diff changeset
155 exit(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
157 }
a61af66fc99e Initial load
duke
parents:
diff changeset
158 return (*os_sigaction)(sig, act, oact);
a61af66fc99e Initial load
duke
parents:
diff changeset
159 }
a61af66fc99e Initial load
duke
parents:
diff changeset
160
a61af66fc99e Initial load
duke
parents:
diff changeset
161 int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
a61af66fc99e Initial load
duke
parents:
diff changeset
162 int res;
a61af66fc99e Initial load
duke
parents:
diff changeset
163 bool sigused;
a61af66fc99e Initial load
duke
parents:
diff changeset
164 struct sigaction oldAct;
a61af66fc99e Initial load
duke
parents:
diff changeset
165
a61af66fc99e Initial load
duke
parents:
diff changeset
166 signal_lock();
a61af66fc99e Initial load
duke
parents:
diff changeset
167
a61af66fc99e Initial load
duke
parents:
diff changeset
168 sigused = (MASK(sig) & jvmsigs) != 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
169 if (jvm_signal_installed && sigused) {
a61af66fc99e Initial load
duke
parents:
diff changeset
170 /* jvm has installed its signal handler for this signal. */
a61af66fc99e Initial load
duke
parents:
diff changeset
171 /* Save the handler. Don't really install it. */
a61af66fc99e Initial load
duke
parents:
diff changeset
172 if (oact != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
173 *oact = sact[sig];
a61af66fc99e Initial load
duke
parents:
diff changeset
174 }
a61af66fc99e Initial load
duke
parents:
diff changeset
175 if (act != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
176 sact[sig] = *act;
a61af66fc99e Initial load
duke
parents:
diff changeset
177 }
a61af66fc99e Initial load
duke
parents:
diff changeset
178
a61af66fc99e Initial load
duke
parents:
diff changeset
179 signal_unlock();
a61af66fc99e Initial load
duke
parents:
diff changeset
180 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
181 } else if (jvm_signal_installing) {
a61af66fc99e Initial load
duke
parents:
diff changeset
182 /* jvm is installing its signal handlers. Install the new
a61af66fc99e Initial load
duke
parents:
diff changeset
183 * handlers and save the old ones. */
a61af66fc99e Initial load
duke
parents:
diff changeset
184 res = call_os_sigaction(sig, act, &oldAct);
a61af66fc99e Initial load
duke
parents:
diff changeset
185 sact[sig] = oldAct;
a61af66fc99e Initial load
duke
parents:
diff changeset
186 if (oact != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
187 *oact = oldAct;
a61af66fc99e Initial load
duke
parents:
diff changeset
188 }
a61af66fc99e Initial load
duke
parents:
diff changeset
189
a61af66fc99e Initial load
duke
parents:
diff changeset
190 /* Record the signals used by jvm */
a61af66fc99e Initial load
duke
parents:
diff changeset
191 jvmsigs |= MASK(sig);
a61af66fc99e Initial load
duke
parents:
diff changeset
192
a61af66fc99e Initial load
duke
parents:
diff changeset
193 signal_unlock();
a61af66fc99e Initial load
duke
parents:
diff changeset
194 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
195 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
196 /* jvm has no relation with this signal (yet). Install the
a61af66fc99e Initial load
duke
parents:
diff changeset
197 * the handler. */
a61af66fc99e Initial load
duke
parents:
diff changeset
198 res = call_os_sigaction(sig, act, oact);
a61af66fc99e Initial load
duke
parents:
diff changeset
199
a61af66fc99e Initial load
duke
parents:
diff changeset
200 signal_unlock();
a61af66fc99e Initial load
duke
parents:
diff changeset
201 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
202 }
a61af66fc99e Initial load
duke
parents:
diff changeset
203 }
a61af66fc99e Initial load
duke
parents:
diff changeset
204
a61af66fc99e Initial load
duke
parents:
diff changeset
205 /* The three functions for the jvm to call into */
a61af66fc99e Initial load
duke
parents:
diff changeset
206 void JVM_begin_signal_setting() {
a61af66fc99e Initial load
duke
parents:
diff changeset
207 signal_lock();
a61af66fc99e Initial load
duke
parents:
diff changeset
208 jvm_signal_installing = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
209 tid = pthread_self();
a61af66fc99e Initial load
duke
parents:
diff changeset
210 signal_unlock();
a61af66fc99e Initial load
duke
parents:
diff changeset
211 }
a61af66fc99e Initial load
duke
parents:
diff changeset
212
a61af66fc99e Initial load
duke
parents:
diff changeset
213 void JVM_end_signal_setting() {
a61af66fc99e Initial load
duke
parents:
diff changeset
214 signal_lock();
a61af66fc99e Initial load
duke
parents:
diff changeset
215 jvm_signal_installed = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
216 jvm_signal_installing = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
217 pthread_cond_broadcast(&cond);
a61af66fc99e Initial load
duke
parents:
diff changeset
218 signal_unlock();
a61af66fc99e Initial load
duke
parents:
diff changeset
219 }
a61af66fc99e Initial load
duke
parents:
diff changeset
220
a61af66fc99e Initial load
duke
parents:
diff changeset
221 struct sigaction *JVM_get_signal_action(int sig) {
a61af66fc99e Initial load
duke
parents:
diff changeset
222 /* Does race condition make sense here? */
a61af66fc99e Initial load
duke
parents:
diff changeset
223 if ((MASK(sig) & jvmsigs) != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
224 return &sact[sig];
a61af66fc99e Initial load
duke
parents:
diff changeset
225 }
a61af66fc99e Initial load
duke
parents:
diff changeset
226 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
227 }