jdk/src/java.base/share/classes/sun/misc/Signal.java
changeset 36009 2dbdf909ac81
parent 34716 7477a052aecc
equal deleted inserted replaced
36008:3113bdef9cb1 36009:2dbdf909ac81
     1 /*
     1 /*
     2  * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
     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.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    22  * or visit www.oracle.com if you need additional information or have any
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package sun.misc;
    26 package sun.misc;
    27 import java.util.Hashtable;
    27 
       
    28 import java.util.Objects;
    28 
    29 
    29 /**
    30 /**
    30  * This class provides ANSI/ISO C signal support. A Java program can register
    31  * 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  * signal handlers for the current process. There are two restrictions:
    32  * <ul>
    33  * <ul>
    66  * Signal.handle(new Signal("INT"), handler);
    67  * Signal.handle(new Signal("INT"), handler);
    67  * </pre></blockquote>
    68  * </pre></blockquote>
    68  *
    69  *
    69  * @author   Sheng Liang
    70  * @author   Sheng Liang
    70  * @author   Bill Shannon
    71  * @author   Bill Shannon
    71  * @see      sun.misc.SignalHandler
    72  * @see     sun.misc.SignalHandler
    72  * @since    1.2
    73  * @since    1.2
    73  */
    74  */
    74 public final class Signal {
    75 public final class Signal {
    75     private static Hashtable<Signal,SignalHandler> handlers = new Hashtable<>(4);
    76 
    76     private static Hashtable<Integer,Signal> signals = new Hashtable<>(4);
    77     // Delegate to jdk.internal.misc.Signal.
    77 
    78     private final jdk.internal.misc.Signal iSignal;
    78     private int number;
       
    79     private String name;
       
    80 
    79 
    81     /* Returns the signal number */
    80     /* Returns the signal number */
    82     public int getNumber() {
    81     public int getNumber() {
    83         return number;
    82         return iSignal.getNumber();
    84     }
    83     }
    85 
    84 
    86     /**
    85     /**
    87      * Returns the signal name.
    86      * Returns the signal name.
    88      *
    87      *
    89      * @return the name of the signal.
    88      * @return the name of the signal.
    90      * @see sun.misc.Signal#Signal(String name)
    89      * @see sun.misc.Signal#Signal(String name)
    91      */
    90      */
    92     public String getName() {
    91     public String getName() {
    93         return name;
    92         return iSignal.getName();
    94     }
    93     }
    95 
    94 
    96     /**
    95     /**
    97      * Compares the equality of two <code>Signal</code> objects.
    96      * Compares the equality of two <code>Signal</code> objects.
    98      *
    97      *
   105         }
   104         }
   106         if (other == null || !(other instanceof Signal)) {
   105         if (other == null || !(other instanceof Signal)) {
   107             return false;
   106             return false;
   108         }
   107         }
   109         Signal other1 = (Signal)other;
   108         Signal other1 = (Signal)other;
   110         return name.equals(other1.name) && (number == other1.number);
   109         return iSignal.equals(other1.iSignal);
   111     }
   110     }
   112 
   111 
   113     /**
   112     /**
   114      * Returns a hashcode for this Signal.
   113      * Returns a hashcode for this Signal.
   115      *
   114      *
   116      * @return  a hash code value for this object.
   115      * @return  a hash code value for this object.
   117      */
   116      */
   118     public int hashCode() {
   117     public int hashCode() {
   119         return number;
   118         return getNumber();
   120     }
   119     }
   121 
   120 
   122     /**
   121     /**
   123      * Returns a string representation of this signal. For example, "SIGINT"
   122      * Returns a string representation of this signal. For example, "SIGINT"
   124      * for an object constructed using <code>new Signal ("INT")</code>.
   123      * for an object constructed using <code>new Signal ("INT")</code>.
   125      *
   124      *
   126      * @return a string representation of the signal
   125      * @return a string representation of the signal
   127      */
   126      */
   128     public String toString() {
   127     public String toString() {
   129         return "SIG" + name;
   128         return iSignal.toString();
   130     }
   129     }
   131 
   130 
   132     /**
   131     /**
   133      * Constructs a signal from its name.
   132      * Constructs a signal from its name.
   134      *
   133      *
   135      * @param name the name of the signal.
   134      * @param name the name of the signal.
   136      * @exception IllegalArgumentException unknown signal
   135      * @exception IllegalArgumentException unknown signal
   137      * @see sun.misc.Signal#getName()
   136      * @see sun.misc.Signal#getName()
   138      */
   137      */
   139     public Signal(String name) {
   138     public Signal(String name) {
   140         number = findSignal(name);
   139         iSignal = new jdk.internal.misc.Signal(name);
   141         this.name = name;
       
   142         if (number < 0) {
       
   143             throw new IllegalArgumentException("Unknown signal: " + name);
       
   144         }
       
   145     }
   140     }
   146 
   141 
   147     /**
   142     /**
   148      * Registers a signal handler.
   143      * Registers a signal handler.
   149      *
   144      *
   157      * @see sun.misc.SignalHandler#SIG_IGN
   152      * @see sun.misc.SignalHandler#SIG_IGN
   158      */
   153      */
   159     public static synchronized SignalHandler handle(Signal sig,
   154     public static synchronized SignalHandler handle(Signal sig,
   160                                                     SignalHandler handler)
   155                                                     SignalHandler handler)
   161         throws IllegalArgumentException {
   156         throws IllegalArgumentException {
   162         long newH = (handler instanceof NativeSignalHandler) ?
   157         jdk.internal.misc.Signal.Handler oldHandler = jdk.internal.misc.Signal.handle(sig.iSignal,
   163                       ((NativeSignalHandler)handler).getHandler() : 2;
   158                 InternalMiscHandler.of(sig, handler));
   164         long oldH = handle0(sig.number, newH);
   159         return SunMiscHandler.of(sig.iSignal, oldHandler);
   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     }
   160     }
   187 
   161 
   188     /**
   162     /**
   189      * Raises a signal in the current process.
   163      * Raises a signal in the current process.
   190      *
   164      *
   191      * @param sig a signal
   165      * @param sig a signal
   192      * @see sun.misc.Signal#handle(Signal sig, SignalHandler handler)
   166      * @see sun.misc.Signal#handle(Signal sig, SignalHandler handler)
   193      */
   167      */
   194     public static void raise(Signal sig) throws IllegalArgumentException {
   168     public static void raise(Signal sig) throws IllegalArgumentException {
   195         if (handlers.get(sig) == null) {
   169         jdk.internal.misc.Signal.raise(sig.iSignal);
   196             throw new IllegalArgumentException("Unhandled signal: " + sig);
   170     }
   197         }
   171 
   198         raise0(sig.number);
   172     /*
   199     }
   173      * Wrapper class to proxy a SignalHandler to a jdk.internal.misc.Signal.Handler.
   200 
   174      */
   201     /* Called by the VM to execute Java signal handlers. */
   175     static final class InternalMiscHandler implements jdk.internal.misc.Signal.Handler {
   202     private static void dispatch(final int number) {
   176         private final SignalHandler handler;
   203         final Signal sig = signals.get(number);
   177         private final Signal signal;
   204         final SignalHandler handler = handlers.get(sig);
   178 
   205 
   179         static jdk.internal.misc.Signal.Handler of(Signal signal, SignalHandler handler) {
   206         Runnable runnable = new Runnable () {
   180             if (handler == SignalHandler.SIG_DFL) {
   207             public void run() {
   181                 return jdk.internal.misc.Signal.Handler.SIG_DFL;
   208               // Don't bother to reset the priority. Signal handler will
   182             } else if (handler == SignalHandler.SIG_IGN) {
   209               // run at maximum priority inherited from the VM signal
   183                 return jdk.internal.misc.Signal.Handler.SIG_IGN;
   210               // dispatch thread.
   184             } else if (handler instanceof SunMiscHandler) {
   211               // Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
   185                 return ((SunMiscHandler)handler).iHandler;
   212                 handler.handle(sig);
   186             } else {
       
   187                 return new InternalMiscHandler(signal, handler);
   213             }
   188             }
   214         };
   189         }
   215         if (handler != null) {
   190 
   216             new Thread(null, runnable, sig + " handler", 0, false).start();
   191         private InternalMiscHandler(Signal signal, SignalHandler handler) {
   217         }
   192             this.handler = handler;
   218     }
   193             this.signal = signal;
   219 
   194         }
   220     /* Find the signal number, given a name. Returns -1 for unknown signals. */
   195 
   221     private static native int findSignal(String sigName);
   196         @Override
   222     /* Registers a native signal handler, and returns the old handler.
   197         public void handle(jdk.internal.misc.Signal ignore) {
   223      * Handler values:
   198             handler.handle(signal);
   224      *   0     default handler
   199         }
   225      *   1     ignore the signal
   200     }
   226      *   2     call back to Signal.dispatch
   201 
   227      *   other arbitrary native signal handlers
   202     /*
   228      */
   203      * Wrapper class to proxy a jdk.internal.misc.Signal.Handler to a SignalHandler.
   229     private static native long handle0(int sig, long nativeH);
   204      */
   230     /* Raise a given signal number */
   205     static final class SunMiscHandler implements SignalHandler {
   231     private static native void raise0(int sig);
   206         private final jdk.internal.misc.Signal iSignal;
       
   207         private final jdk.internal.misc.Signal.Handler iHandler;
       
   208 
       
   209         static SignalHandler of(jdk.internal.misc.Signal signal, jdk.internal.misc.Signal.Handler handler) {
       
   210             if (handler == jdk.internal.misc.Signal.Handler.SIG_DFL) {
       
   211                 return SignalHandler.SIG_DFL;
       
   212             } else if (handler == jdk.internal.misc.Signal.Handler.SIG_IGN) {
       
   213                 return SignalHandler.SIG_IGN;
       
   214             } else if (handler instanceof InternalMiscHandler) {
       
   215                 return ((InternalMiscHandler) handler).handler;
       
   216             } else {
       
   217                 return new SunMiscHandler(signal, handler);
       
   218             }
       
   219         }
       
   220 
       
   221         SunMiscHandler(jdk.internal.misc.Signal iSignal, jdk.internal.misc.Signal.Handler iHandler) {
       
   222             this.iSignal = iSignal;
       
   223             this.iHandler = iHandler;
       
   224         }
       
   225 
       
   226         @Override
       
   227         public void handle(Signal sig) {
       
   228             iHandler.handle(iSignal);
       
   229         }
       
   230 
       
   231         public String toString() {
       
   232             return iHandler.toString();
       
   233         }
       
   234     }
   232 }
   235 }