--- old/src/java.base/share/classes/sun/misc/Signal.java 2016-02-02 16:50:24.127993503 +0100 +++ new/src/java.base/share/classes/sun/misc/Signal.java 2016-02-02 16:50:24.029995374 +0100 @@ -24,7 +24,11 @@ */ 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.BiConsumer; /** * This class provides ANSI/ISO C signal support. A Java program can register @@ -72,15 +76,14 @@ * @since 1.2 */ public final class Signal { - private static Hashtable handlers = new Hashtable<>(4); - private static Hashtable signals = new Hashtable<>(4); - private int number; - private String name; + private static final Map handlers = new ConcurrentHashMap<>(4); + + private final java.util.Signal utSignal; /* Returns the signal number */ public int getNumber() { - return number; + return utSignal.number(); } /** @@ -90,7 +93,7 @@ * @see sun.misc.Signal#Signal(String name) */ public String getName() { - return name; + return utSignal.name(); } /** @@ -106,8 +109,7 @@ 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; } /** @@ -116,7 +118,7 @@ * @return a hash code value for this object. */ public int hashCode() { - return number; + return getNumber(); } /** @@ -126,7 +128,7 @@ * @return a string representation of the signal */ public String toString() { - return "SIG" + name; + return getName(); } /** @@ -137,11 +139,11 @@ * @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; } /** @@ -159,30 +161,21 @@ 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 = UtHandler.create(handler); + UtHandler oldUtHandler = 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."); } } + + newUtHandler.registerTo(sig.utSignal); + + return (oldUtHandler == null) ? null : oldUtHandler.signalHandler; } /** @@ -192,41 +185,71 @@ * @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(); } - /* 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(); + // 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); } - } - /* 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); + 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 BiConsumer { + Java(SignalHandler signalHandler) { + super(signalHandler); + } + + @Override + public void accept(java.util.Signal uSignal, Runnable runnable) { + signalHandler.handle(new Signal(uSignal)); + } + + @Override + void registerTo(java.util.Signal utSignal) { + utSignal.register(this); + } + + @Override + boolean unregisterFrom(java.util.Signal utSignal) { + return utSignal.unregister(this); + } + } + + private static class Native extends UtHandler { + Native(NativeSignalHandler signalHandler) { + super(signalHandler); + } + + @Override + void registerTo(java.util.Signal utSignal) { + ((NativeSignal) utSignal).registerNative( + ((NativeSignalHandler) signalHandler).getHandler() + ); + } + + @Override + boolean unregisterFrom(java.util.Signal utSignal) { + return ((NativeSignal) utSignal).unregisterNative( + ((NativeSignalHandler) signalHandler).getHandler() + ); + } + } + } }