< prev index next >
src/java.base/share/classes/sun/misc/Signal.java
Print this page
@@ -22,11 +22,15 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.misc;
-import java.util.Hashtable;
+import jdk.internal.misc.NativeSignal;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Consumer;
/**
* This class provides ANSI/ISO C signal support. A Java program can register
* signal handlers for the current process. There are two restrictions:
* <ul>
@@ -70,29 +74,28 @@
* @author Bill Shannon
* @see sun.misc.SignalHandler
* @since 1.2
*/
public final class Signal {
- private static Hashtable<Signal,SignalHandler> handlers = new Hashtable<>(4);
- private static Hashtable<Integer,Signal> signals = new Hashtable<>(4);
- private int number;
- private String name;
+ private static final Map<Integer, UtHandler> handlers = new ConcurrentHashMap<>(4);
+
+ private final java.util.Signal utSignal;
/* Returns the signal number */
public int getNumber() {
- return number;
+ return utSignal.number();
}
/**
* Returns the signal name.
*
* @return the name of the signal.
* @see sun.misc.Signal#Signal(String name)
*/
public String getName() {
- return name;
+ return utSignal.name();
}
/**
* Compares the equality of two <code>Signal</code> objects.
*
@@ -104,46 +107,45 @@
return true;
}
if (other == null || !(other instanceof Signal)) {
return false;
}
- Signal other1 = (Signal)other;
- return name.equals(other1.name) && (number == other1.number);
+ return utSignal == ((Signal) other).utSignal;
}
/**
* Returns a hashcode for this Signal.
*
* @return a hash code value for this object.
*/
public int hashCode() {
- return number;
+ return getNumber();
}
/**
* Returns a string representation of this signal. For example, "SIGINT"
* for an object constructed using <code>new Signal ("INT")</code>.
*
* @return a string representation of the signal
*/
public String toString() {
- return "SIG" + name;
+ return getName();
}
/**
* Constructs a signal from its name.
*
* @param name the name of the signal.
* @exception IllegalArgumentException unknown signal
* @see sun.misc.Signal#getName()
*/
public Signal(String name) {
- number = findSignal(name);
- this.name = name;
- if (number < 0) {
- throw new IllegalArgumentException("Unknown signal: " + name);
+ this(java.util.Signal.of("SIG" + name));
}
+
+ private Signal(java.util.Signal utSignal) {
+ this.utSignal = utSignal;
}
/**
* Registers a signal handler.
*
@@ -157,76 +159,101 @@
* @see sun.misc.SignalHandler#SIG_IGN
*/
public static synchronized SignalHandler handle(Signal sig,
SignalHandler handler)
throws IllegalArgumentException {
- long newH = (handler instanceof NativeSignalHandler) ?
- ((NativeSignalHandler)handler).getHandler() : 2;
- long oldH = handle0(sig.number, newH);
- if (oldH == -1) {
- throw new IllegalArgumentException
- ("Signal already used by VM or OS: " + sig);
- }
- signals.put(sig.number, sig);
- synchronized (handlers) {
- SignalHandler oldHandler = handlers.get(sig);
- handlers.remove(sig);
- if (newH == 2) {
- handlers.put(sig, handler);
- }
- if (oldH == 0) {
- return SignalHandler.SIG_DFL;
- } else if (oldH == 1) {
- return SignalHandler.SIG_IGN;
- } else if (oldH == 2) {
- return oldHandler;
- } else {
- return new NativeSignalHandler(oldH);
+
+ UtHandler newUtHandler = handler == null ? null : UtHandler.create(handler);
+ UtHandler oldUtHandler = newUtHandler == null
+ ? handlers.remove(sig.getNumber())
+ : handlers.put(sig.getNumber(), newUtHandler);
+
+ if (oldUtHandler != null) {
+ if (!oldUtHandler.unregisterFrom(sig.utSignal)) {
+ throw new IllegalStateException(
+ "Can't unregister old sun.misc.SignalHandler as some new " +
+ "handler has been registered with java.util.Signal API.");
+ }
}
+
+ if (newUtHandler != null) {
+ newUtHandler.registerTo(sig.utSignal);
}
+
+ return oldUtHandler == null ? null : oldUtHandler.signalHandler;
}
/**
* Raises a signal in the current process.
*
* @param sig a signal
* @see sun.misc.Signal#handle(Signal sig, SignalHandler handler)
*/
public static void raise(Signal sig) throws IllegalArgumentException {
- if (handlers.get(sig) == null) {
+ if (handlers.get(sig.getNumber()) == null) {
throw new IllegalArgumentException("Unhandled signal: " + sig);
}
- raise0(sig.number);
+ sig.utSignal.raise();
+ }
+
+ // abstraction of Java and Native handlers for java.util.Signal API
+ // with delegation to sun.misc.[SignalHandler|NativeSignalHandler]
+ private static abstract class UtHandler {
+ final SignalHandler signalHandler;
+
+ static UtHandler create(SignalHandler signalHandler) {
+ return (signalHandler instanceof NativeSignalHandler)
+ ? new UtHandler.Native((NativeSignalHandler) signalHandler)
+ : new UtHandler.Java(signalHandler);
+ }
+
+ UtHandler(SignalHandler signalHandler) {
+ this.signalHandler = signalHandler;
+ }
+
+ abstract void registerTo(java.util.Signal utSignal);
+
+ abstract boolean unregisterFrom(java.util.Signal utSignal);
+
+ private static class Java extends UtHandler
+ implements Consumer<java.util.Signal> {
+ Java(SignalHandler signalHandler) {
+ super(signalHandler);
+ }
+
+ @Override
+ public void accept(java.util.Signal uSignal) {
+ signalHandler.handle(new Signal(uSignal));
+ }
+
+ @Override
+ void registerTo(java.util.Signal utSignal) {
+ utSignal.register(this);
}
- /* Called by the VM to execute Java signal handlers. */
- private static void dispatch(final int number) {
- final Signal sig = signals.get(number);
- final SignalHandler handler = handlers.get(sig);
-
- Runnable runnable = new Runnable () {
- public void run() {
- // Don't bother to reset the priority. Signal handler will
- // run at maximum priority inherited from the VM signal
- // dispatch thread.
- // Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
- handler.handle(sig);
- }
- };
- if (handler != null) {
- new Thread(null, runnable, sig + " handler", 0, false).start();
+ @Override
+ boolean unregisterFrom(java.util.Signal utSignal) {
+ return utSignal.unregister(this);
}
}
- /* Find the signal number, given a name. Returns -1 for unknown signals. */
- private static native int findSignal(String sigName);
- /* Registers a native signal handler, and returns the old handler.
- * Handler values:
- * 0 default handler
- * 1 ignore the signal
- * 2 call back to Signal.dispatch
- * other arbitrary native signal handlers
- */
- private static native long handle0(int sig, long nativeH);
- /* Raise a given signal number */
- private static native void raise0(int sig);
+ private static class Native extends UtHandler {
+ Native(NativeSignalHandler signalHandler) {
+ super(signalHandler);
+ }
+
+ @Override
+ void registerTo(java.util.Signal utSignal) {
+ ((NativeSignal) utSignal).register(
+ ((NativeSignalHandler) signalHandler).getHandler()
+ );
+ }
+
+ @Override
+ boolean unregisterFrom(java.util.Signal utSignal) {
+ return ((NativeSignal) utSignal).unregister(
+ ((NativeSignalHandler) signalHandler).getHandler()
+ );
+ }
+ }
+ }
}
< prev index next >