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 sun.misc;
27 import java.util.Hashtable;
28
29 /**
30 * This class provides ANSI/ISO C signal support. A Java program can register
31 * signal handlers for the current process. There are two restrictions:
32 * <ul>
33 * <li>
34 * Java code cannot register a handler for signals that are already used
35 * by the Java VM implementation. The <code>Signal.handle</code>
36 * function raises an <code>IllegalArgumentException</code> if such an attempt
37 * is made.
38 * <li>
39 * When <code>Signal.handle</code> is called, the VM internally registers a
40 * special C signal handler. There is no way to force the Java signal handler
41 * to run synchronously before the C signal handler returns. Instead, when the
42 * VM receives a signal, the special C signal handler creates a new thread
43 * (at priority <code>Thread.MAX_PRIORITY</code>) to
44 * run the registered Java signal handler. The C signal handler immediately
45 * returns. Note that because the Java signal handler runs in a newly created
46 * thread, it may not actually be executed until some time after the C signal
47 * handler returns.
55 * typically produced when the user presses <code>Ctrl-C</code> at the command line.
56 * The <code>Signal</code> constructor throws <code>IllegalArgumentException</code>
57 * when it is passed an unknown signal.
58 * <p>
59 * This is an example of how Java code handles <code>SIGINT</code>:
60 * <blockquote><pre>
61 * SignalHandler handler = new SignalHandler () {
62 * public void handle(Signal sig) {
63 * ... // handle SIGINT
64 * }
65 * };
66 * Signal.handle(new Signal("INT"), handler);
67 * </pre></blockquote>
68 *
69 * @author Sheng Liang
70 * @author Bill Shannon
71 * @see sun.misc.SignalHandler
72 * @since 1.2
73 */
74 public final class Signal {
75 private static Hashtable<Signal,SignalHandler> handlers = new Hashtable<>(4);
76 private static Hashtable<Integer,Signal> signals = new Hashtable<>(4);
77
78 private int number;
79 private String name;
80
81 /* Returns the signal number */
82 public int getNumber() {
83 return number;
84 }
85
86 /**
87 * Returns the signal name.
88 *
89 * @return the name of the signal.
90 * @see sun.misc.Signal#Signal(String name)
91 */
92 public String getName() {
93 return name;
94 }
95
96 /**
97 * Compares the equality of two <code>Signal</code> objects.
98 *
99 * @param other the object to compare with.
100 * @return whether two <code>Signal</code> objects are equal.
101 */
102 public boolean equals(Object other) {
103 if (this == other) {
104 return true;
105 }
106 if (other == null || !(other instanceof Signal)) {
107 return false;
108 }
109 Signal other1 = (Signal)other;
110 return name.equals(other1.name) && (number == other1.number);
111 }
112
113 /**
114 * Returns a hashcode for this Signal.
115 *
116 * @return a hash code value for this object.
117 */
118 public int hashCode() {
119 return number;
120 }
121
122 /**
123 * Returns a string representation of this signal. For example, "SIGINT"
124 * for an object constructed using <code>new Signal ("INT")</code>.
125 *
126 * @return a string representation of the signal
127 */
128 public String toString() {
129 return "SIG" + name;
130 }
131
132 /**
133 * Constructs a signal from its name.
134 *
135 * @param name the name of the signal.
136 * @exception IllegalArgumentException unknown signal
137 * @see sun.misc.Signal#getName()
138 */
139 public Signal(String name) {
140 number = findSignal(name);
141 this.name = name;
142 if (number < 0) {
143 throw new IllegalArgumentException("Unknown signal: " + name);
144 }
145 }
146
147 /**
148 * Registers a signal handler.
149 *
150 * @param sig a signal
151 * @param handler the handler to be registered with the given signal.
152 * @return the old handler
153 * @exception IllegalArgumentException the signal is in use by the VM
154 * @see sun.misc.Signal#raise(Signal sig)
155 * @see sun.misc.SignalHandler
156 * @see sun.misc.SignalHandler#SIG_DFL
157 * @see sun.misc.SignalHandler#SIG_IGN
158 */
159 public static synchronized SignalHandler handle(Signal sig,
160 SignalHandler handler)
161 throws IllegalArgumentException {
162 long newH = (handler instanceof NativeSignalHandler) ?
163 ((NativeSignalHandler)handler).getHandler() : 2;
164 long oldH = handle0(sig.number, newH);
165 if (oldH == -1) {
166 throw new IllegalArgumentException
167 ("Signal already used by VM or OS: " + sig);
168 }
169 signals.put(sig.number, sig);
170 synchronized (handlers) {
171 SignalHandler oldHandler = handlers.get(sig);
172 handlers.remove(sig);
173 if (newH == 2) {
174 handlers.put(sig, handler);
175 }
176 if (oldH == 0) {
177 return SignalHandler.SIG_DFL;
178 } else if (oldH == 1) {
179 return SignalHandler.SIG_IGN;
180 } else if (oldH == 2) {
181 return oldHandler;
182 } else {
183 return new NativeSignalHandler(oldH);
184 }
185 }
186 }
187
188 /**
189 * Raises a signal in the current process.
190 *
191 * @param sig a signal
192 * @see sun.misc.Signal#handle(Signal sig, SignalHandler handler)
193 */
194 public static void raise(Signal sig) throws IllegalArgumentException {
195 if (handlers.get(sig) == null) {
196 throw new IllegalArgumentException("Unhandled signal: " + sig);
197 }
198 raise0(sig.number);
199 }
200
201 /* Called by the VM to execute Java signal handlers. */
202 private static void dispatch(final int number) {
203 final Signal sig = signals.get(number);
204 final SignalHandler handler = handlers.get(sig);
205
206 Runnable runnable = new Runnable () {
207 public void run() {
208 // Don't bother to reset the priority. Signal handler will
209 // run at maximum priority inherited from the VM signal
210 // dispatch thread.
211 // Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
212 handler.handle(sig);
213 }
214 };
215 if (handler != null) {
216 new Thread(null, runnable, sig + " handler", 0, false).start();
217 }
218 }
219
220 /* Find the signal number, given a name. Returns -1 for unknown signals. */
221 private static native int findSignal(String sigName);
222 /* Registers a native signal handler, and returns the old handler.
223 * Handler values:
224 * 0 default handler
225 * 1 ignore the signal
226 * 2 call back to Signal.dispatch
227 * other arbitrary native signal handlers
228 */
229 private static native long handle0(int sig, long nativeH);
230 /* Raise a given signal number */
231 private static native void raise0(int sig);
232 }
|
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 sun.misc;
27 import jdk.internal.misc.NativeSignal;
28
29 import java.util.Map;
30 import java.util.concurrent.ConcurrentHashMap;
31 import java.util.function.Consumer;
32
33 /**
34 * This class provides ANSI/ISO C signal support. A Java program can register
35 * signal handlers for the current process. There are two restrictions:
36 * <ul>
37 * <li>
38 * Java code cannot register a handler for signals that are already used
39 * by the Java VM implementation. The <code>Signal.handle</code>
40 * function raises an <code>IllegalArgumentException</code> if such an attempt
41 * is made.
42 * <li>
43 * When <code>Signal.handle</code> is called, the VM internally registers a
44 * special C signal handler. There is no way to force the Java signal handler
45 * to run synchronously before the C signal handler returns. Instead, when the
46 * VM receives a signal, the special C signal handler creates a new thread
47 * (at priority <code>Thread.MAX_PRIORITY</code>) to
48 * run the registered Java signal handler. The C signal handler immediately
49 * returns. Note that because the Java signal handler runs in a newly created
50 * thread, it may not actually be executed until some time after the C signal
51 * handler returns.
59 * typically produced when the user presses <code>Ctrl-C</code> at the command line.
60 * The <code>Signal</code> constructor throws <code>IllegalArgumentException</code>
61 * when it is passed an unknown signal.
62 * <p>
63 * This is an example of how Java code handles <code>SIGINT</code>:
64 * <blockquote><pre>
65 * SignalHandler handler = new SignalHandler () {
66 * public void handle(Signal sig) {
67 * ... // handle SIGINT
68 * }
69 * };
70 * Signal.handle(new Signal("INT"), handler);
71 * </pre></blockquote>
72 *
73 * @author Sheng Liang
74 * @author Bill Shannon
75 * @see sun.misc.SignalHandler
76 * @since 1.2
77 */
78 public final class Signal {
79
80 private static final Map<Integer, UtHandler> handlers = new ConcurrentHashMap<>(4);
81
82 private final java.util.Signal utSignal;
83
84 /* Returns the signal number */
85 public int getNumber() {
86 return utSignal.number();
87 }
88
89 /**
90 * Returns the signal name.
91 *
92 * @return the name of the signal.
93 * @see sun.misc.Signal#Signal(String name)
94 */
95 public String getName() {
96 return utSignal.name();
97 }
98
99 /**
100 * Compares the equality of two <code>Signal</code> objects.
101 *
102 * @param other the object to compare with.
103 * @return whether two <code>Signal</code> objects are equal.
104 */
105 public boolean equals(Object other) {
106 if (this == other) {
107 return true;
108 }
109 if (other == null || !(other instanceof Signal)) {
110 return false;
111 }
112 return utSignal == ((Signal) other).utSignal;
113 }
114
115 /**
116 * Returns a hashcode for this Signal.
117 *
118 * @return a hash code value for this object.
119 */
120 public int hashCode() {
121 return getNumber();
122 }
123
124 /**
125 * Returns a string representation of this signal. For example, "SIGINT"
126 * for an object constructed using <code>new Signal ("INT")</code>.
127 *
128 * @return a string representation of the signal
129 */
130 public String toString() {
131 return getName();
132 }
133
134 /**
135 * Constructs a signal from its name.
136 *
137 * @param name the name of the signal.
138 * @exception IllegalArgumentException unknown signal
139 * @see sun.misc.Signal#getName()
140 */
141 public Signal(String name) {
142 this(java.util.Signal.of("SIG" + name));
143 }
144
145 private Signal(java.util.Signal utSignal) {
146 this.utSignal = utSignal;
147 }
148
149 /**
150 * Registers a signal handler.
151 *
152 * @param sig a signal
153 * @param handler the handler to be registered with the given signal.
154 * @return the old handler
155 * @exception IllegalArgumentException the signal is in use by the VM
156 * @see sun.misc.Signal#raise(Signal sig)
157 * @see sun.misc.SignalHandler
158 * @see sun.misc.SignalHandler#SIG_DFL
159 * @see sun.misc.SignalHandler#SIG_IGN
160 */
161 public static synchronized SignalHandler handle(Signal sig,
162 SignalHandler handler)
163 throws IllegalArgumentException {
164
165 UtHandler newUtHandler = handler == null ? null : UtHandler.create(handler);
166 UtHandler oldUtHandler = newUtHandler == null
167 ? handlers.remove(sig.getNumber())
168 : handlers.put(sig.getNumber(), newUtHandler);
169
170 if (oldUtHandler != null) {
171 if (!oldUtHandler.unregisterFrom(sig.utSignal)) {
172 throw new IllegalStateException(
173 "Can't unregister old sun.misc.SignalHandler as some new " +
174 "handler has been registered with java.util.Signal API.");
175 }
176 }
177
178 if (newUtHandler != null) {
179 newUtHandler.registerTo(sig.utSignal);
180 }
181
182 return oldUtHandler == null ? null : oldUtHandler.signalHandler;
183 }
184
185 /**
186 * Raises a signal in the current process.
187 *
188 * @param sig a signal
189 * @see sun.misc.Signal#handle(Signal sig, SignalHandler handler)
190 */
191 public static void raise(Signal sig) throws IllegalArgumentException {
192 if (handlers.get(sig.getNumber()) == null) {
193 throw new IllegalArgumentException("Unhandled signal: " + sig);
194 }
195 sig.utSignal.raise();
196 }
197
198 // abstraction of Java and Native handlers for java.util.Signal API
199 // with delegation to sun.misc.[SignalHandler|NativeSignalHandler]
200 private static abstract class UtHandler {
201 final SignalHandler signalHandler;
202
203 static UtHandler create(SignalHandler signalHandler) {
204 return (signalHandler instanceof NativeSignalHandler)
205 ? new UtHandler.Native((NativeSignalHandler) signalHandler)
206 : new UtHandler.Java(signalHandler);
207 }
208
209 UtHandler(SignalHandler signalHandler) {
210 this.signalHandler = signalHandler;
211 }
212
213 abstract void registerTo(java.util.Signal utSignal);
214
215 abstract boolean unregisterFrom(java.util.Signal utSignal);
216
217 private static class Java extends UtHandler
218 implements Consumer<java.util.Signal> {
219 Java(SignalHandler signalHandler) {
220 super(signalHandler);
221 }
222
223 @Override
224 public void accept(java.util.Signal uSignal) {
225 signalHandler.handle(new Signal(uSignal));
226 }
227
228 @Override
229 void registerTo(java.util.Signal utSignal) {
230 utSignal.register(this);
231 }
232
233 @Override
234 boolean unregisterFrom(java.util.Signal utSignal) {
235 return utSignal.unregister(this);
236 }
237 }
238
239 private static class Native extends UtHandler {
240 Native(NativeSignalHandler signalHandler) {
241 super(signalHandler);
242 }
243
244 @Override
245 void registerTo(java.util.Signal utSignal) {
246 ((NativeSignal) utSignal).register(
247 ((NativeSignalHandler) signalHandler).getHandler()
248 );
249 }
250
251 @Override
252 boolean unregisterFrom(java.util.Signal utSignal) {
253 return ((NativeSignal) utSignal).unregister(
254 ((NativeSignalHandler) signalHandler).getHandler()
255 );
256 }
257 }
258 }
259 }
|