Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/jdk/internal/misc/Signal.java
41159 views
1
/*
2
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package jdk.internal.misc;
27
28
import java.util.Hashtable;
29
import java.util.Objects;
30
31
/**
32
* This class provides ANSI/ISO C signal support. A Java program can register
33
* signal handlers for the current process. There are two restrictions:
34
* <ul>
35
* <li>
36
* Java code cannot register a handler for signals that are already used
37
* by the Java VM implementation. The <code>Signal.handle</code>
38
* function raises an <code>IllegalArgumentException</code> if such an attempt
39
* is made.
40
* <li>
41
* When <code>Signal.handle</code> is called, the VM internally registers a
42
* special C signal handler. There is no way to force the Java signal handler
43
* to run synchronously before the C signal handler returns. Instead, when the
44
* VM receives a signal, the special C signal handler creates a new thread
45
* (at priority <code>Thread.MAX_PRIORITY</code>) to
46
* run the registered Java signal handler. The C signal handler immediately
47
* returns. Note that because the Java signal handler runs in a newly created
48
* thread, it may not actually be executed until some time after the C signal
49
* handler returns.
50
* </ul>
51
* <p>
52
* Signal objects are created based on their names. For example:
53
* <blockquote><pre>
54
* new Signal("INT");
55
* </pre></blockquote>
56
* constructs a signal object corresponding to <code>SIGINT</code>, which is
57
* typically produced when the user presses <code>Ctrl-C</code> at the command line.
58
* The <code>Signal</code> constructor throws <code>IllegalArgumentException</code>
59
* when it is passed an unknown signal.
60
* <p>
61
* This is an example of how Java code handles <code>SIGINT</code>:
62
* <blockquote><pre>
63
* Signal.Handler handler = new Signal.Handler () {
64
* public void handle(Signal sig) {
65
* ... // handle SIGINT
66
* }
67
* };
68
* Signal.handle(new Signal("INT"), handler);
69
* </pre></blockquote>
70
*
71
* @since 9
72
*/
73
public final class Signal {
74
private static Hashtable<Signal, Signal.Handler> handlers = new Hashtable<>(4);
75
private static Hashtable<Integer, Signal> signals = new Hashtable<>(4);
76
77
private int number;
78
private String name;
79
80
/* Returns the signal number */
81
public int getNumber() {
82
return number;
83
}
84
85
/**
86
* Returns the signal name.
87
*
88
* @return the name of the signal.
89
* @see jdk.internal.misc.Signal#Signal(String name)
90
*/
91
public String getName() {
92
return name;
93
}
94
95
/**
96
* Compares the equality of two <code>Signal</code> objects.
97
*
98
* @param obj the object to compare with.
99
* @return whether two <code>Signal</code> objects are equal.
100
*/
101
public boolean equals(Object obj) {
102
if (this == obj) {
103
return true;
104
}
105
if (obj instanceof Signal other) {
106
return name.equals(other.name) && (number == other.number);
107
}
108
return false;
109
}
110
111
/**
112
* Returns a hashcode for this Signal.
113
*
114
* @return a hash code value for this object.
115
*/
116
public int hashCode() {
117
return number;
118
}
119
120
/**
121
* Returns a string representation of this signal. For example, "SIGINT"
122
* for an object constructed using <code>new Signal ("INT")</code>.
123
*
124
* @return a string representation of the signal
125
*/
126
public String toString() {
127
return "SIG" + name;
128
}
129
130
/**
131
* Constructs a signal from its name.
132
*
133
* @param name the name of the signal.
134
* @exception IllegalArgumentException unknown signal
135
* @see jdk.internal.misc.Signal#getName()
136
*/
137
public Signal(String name) {
138
Objects.requireNonNull(name, "name");
139
// Signal names are the short names;
140
// the "SIG" prefix is not used for compatibility with previous JDKs
141
if (name.startsWith("SIG")) {
142
throw new IllegalArgumentException("Unknown signal: " + name);
143
}
144
this.name = name;
145
number = findSignal0(name);
146
if (number < 0) {
147
throw new IllegalArgumentException("Unknown signal: " + name);
148
}
149
}
150
151
/**
152
* Registers a signal handler.
153
*
154
* @param sig a signal
155
* @param handler the handler to be registered with the given signal.
156
* @return the old handler
157
* @exception IllegalArgumentException the signal is in use by the VM
158
* @see jdk.internal.misc.Signal#raise(Signal sig)
159
* @see jdk.internal.misc.Signal.Handler
160
* @see jdk.internal.misc.Signal.Handler#SIG_DFL
161
* @see jdk.internal.misc.Signal.Handler#SIG_IGN
162
*/
163
public static synchronized Signal.Handler handle(Signal sig,
164
Signal.Handler handler)
165
throws IllegalArgumentException {
166
Objects.requireNonNull(sig, "sig");
167
Objects.requireNonNull(handler, "handler");
168
long newH = (handler instanceof NativeHandler) ?
169
((NativeHandler)handler).getHandler() : 2;
170
long oldH = handle0(sig.number, newH);
171
if (oldH == -1) {
172
throw new IllegalArgumentException
173
("Signal already used by VM or OS: " + sig);
174
}
175
signals.put(sig.number, sig);
176
synchronized (handlers) {
177
Signal.Handler oldHandler = handlers.get(sig);
178
handlers.remove(sig);
179
if (newH == 2) {
180
handlers.put(sig, handler);
181
}
182
if (oldH == 0) {
183
return Signal.Handler.SIG_DFL;
184
} else if (oldH == 1) {
185
return Signal.Handler.SIG_IGN;
186
} else if (oldH == 2) {
187
return oldHandler;
188
} else {
189
return new NativeHandler(oldH);
190
}
191
}
192
}
193
194
/**
195
* Raises a signal in the current process.
196
*
197
* @param sig a signal
198
* @see jdk.internal.misc.Signal#handle(Signal sig, Signal.Handler handler)
199
*/
200
public static void raise(Signal sig) throws IllegalArgumentException {
201
Objects.requireNonNull(sig, "sig");
202
if (handlers.get(sig) == null) {
203
throw new IllegalArgumentException("Unhandled signal: " + sig);
204
}
205
raise0(sig.number);
206
}
207
208
/* Called by the VM to execute Java signal handlers. */
209
private static void dispatch(final int number) {
210
final Signal sig = signals.get(number);
211
final Signal.Handler handler = handlers.get(sig);
212
213
Runnable runnable = new Runnable () {
214
public void run() {
215
// Don't bother to reset the priority. Signal handler will
216
// run at maximum priority inherited from the VM signal
217
// dispatch thread.
218
// Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
219
handler.handle(sig);
220
}
221
};
222
if (handler != null) {
223
new Thread(null, runnable, sig + " handler", 0, false).start();
224
}
225
}
226
227
/* Find the signal number, given a name. Returns -1 for unknown signals. */
228
private static native int findSignal0(String sigName);
229
/* Registers a native signal handler, and returns the old handler.
230
* Handler values:
231
* 0 default handler
232
* 1 ignore the signal
233
* 2 call back to Signal.dispatch
234
* other arbitrary native signal handlers
235
*/
236
private static native long handle0(int sig, long nativeH);
237
/* Raise a given signal number */
238
private static native void raise0(int sig);
239
240
/**
241
* This is the signal handler interface expected in <code>Signal.handle</code>.
242
*/
243
public interface Handler {
244
245
/**
246
* The default signal handler
247
*/
248
public static final Signal.Handler SIG_DFL = new NativeHandler(0);
249
/**
250
* Ignore the signal
251
*/
252
public static final Signal.Handler SIG_IGN = new NativeHandler(1);
253
254
/**
255
* Handle the given signal
256
*
257
* @param sig a signal object
258
*/
259
public void handle(Signal sig);
260
}
261
262
263
/*
264
* A package-private class implementing a signal handler in native code.
265
*/
266
static final class NativeHandler implements Signal.Handler {
267
268
private final long handler;
269
270
long getHandler() {
271
return handler;
272
}
273
274
NativeHandler(long handler) {
275
this.handler = handler;
276
}
277
278
public void handle(Signal sig) {
279
throw new UnsupportedOperationException("invoking native signal handle not supported");
280
}
281
282
public String toString() {
283
return this == SIG_DFL ? "SIG_DFL" :
284
(this == SIG_IGN ? "SIG_IGN" : super.toString());
285
}
286
}
287
288
}
289
290