< 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 >