1/* 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. 4 * 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 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 26package sun.misc; 27 28import java.util.Objects; 29 30/** 31 * This class provides ANSI/ISO C signal support. A Java program can register 32 * signal handlers for the current process. There are two restrictions: 33 * <ul> 34 * <li> 35 * Java code cannot register a handler for signals that are already used 36 * by the Java VM implementation. The <code>Signal.handle</code> 37 * function raises an <code>IllegalArgumentException</code> if such an attempt 38 * is made. 39 * <li> 40 * When <code>Signal.handle</code> is called, the VM internally registers a 41 * special C signal handler. There is no way to force the Java signal handler 42 * to run synchronously before the C signal handler returns. Instead, when the 43 * VM receives a signal, the special C signal handler creates a new thread 44 * (at priority <code>Thread.MAX_PRIORITY</code>) to 45 * run the registered Java signal handler. The C signal handler immediately 46 * returns. Note that because the Java signal handler runs in a newly created 47 * thread, it may not actually be executed until some time after the C signal 48 * handler returns. 49 * </ul> 50 * <p> 51 * Signal objects are created based on their names. For example: 52 * <blockquote><pre> 53 * new Signal("INT"); 54 * </pre></blockquote> 55 * constructs a signal object corresponding to <code>SIGINT</code>, which is 56 * typically produced when the user presses <code>Ctrl-C</code> at the command line. 57 * The <code>Signal</code> constructor throws <code>IllegalArgumentException</code> 58 * when it is passed an unknown signal. 59 * <p> 60 * This is an example of how Java code handles <code>SIGINT</code>: 61 * <blockquote><pre> 62 * SignalHandler handler = new SignalHandler () { 63 * public void handle(Signal sig) { 64 * ... // handle SIGINT 65 * } 66 * }; 67 * Signal.handle(new Signal("INT"), handler); 68 * </pre></blockquote> 69 * 70 * @author Sheng Liang 71 * @author Bill Shannon 72 * @see sun.misc.SignalHandler 73 * @since 1.2 74 */ 75public final class Signal { 76 77 // Delegate to jdk.internal.misc.Signal. 78 private final jdk.internal.misc.Signal iSignal; 79 80 /* Returns the signal number */ 81 public int getNumber() { 82 return iSignal.getNumber(); 83 } 84 85 /** 86 * Returns the signal name. 87 * 88 * @return the name of the signal. 89 * @see sun.misc.Signal#Signal(String name) 90 */ 91 public String getName() { 92 return iSignal.getName(); 93 } 94 95 /** 96 * Compares the equality of two <code>Signal</code> objects. 97 * 98 * @param other the object to compare with. 99 * @return whether two <code>Signal</code> objects are equal. 100 */ 101 public boolean equals(Object other) { 102 if (this == other) { 103 return true; 104 } 105 if (other == null || !(other instanceof Signal)) { 106 return false; 107 } 108 Signal other1 = (Signal)other; 109 return iSignal.equals(other1.iSignal); 110 } 111 112 /** 113 * Returns a hashcode for this Signal. 114 * 115 * @return a hash code value for this object. 116 */ 117 public int hashCode() { 118 return getNumber(); 119 } 120 121 /** 122 * Returns a string representation of this signal. For example, "SIGINT" 123 * for an object constructed using <code>new Signal ("INT")</code>. 124 * 125 * @return a string representation of the signal 126 */ 127 public String toString() { 128 return iSignal.toString(); 129 } 130 131 /** 132 * Constructs a signal from its name. 133 * 134 * @param name the name of the signal. 135 * @exception IllegalArgumentException unknown signal 136 * @see sun.misc.Signal#getName() 137 */ 138 public Signal(String name) { 139 iSignal = new jdk.internal.misc.Signal(name); 140 } 141 142 /** 143 * Registers a signal handler. 144 * 145 * @param sig a signal 146 * @param handler the handler to be registered with the given signal. 147 * @return the old handler 148 * @exception IllegalArgumentException the signal is in use by the VM 149 * @see sun.misc.Signal#raise(Signal sig) 150 * @see sun.misc.SignalHandler 151 * @see sun.misc.SignalHandler#SIG_DFL 152 * @see sun.misc.SignalHandler#SIG_IGN 153 */ 154 public static synchronized SignalHandler handle(Signal sig, 155 SignalHandler handler) 156 throws IllegalArgumentException { 157 jdk.internal.misc.Signal.Handler oldHandler = jdk.internal.misc.Signal.handle(sig.iSignal, 158 InternalMiscHandler.of(sig, handler)); 159 return SunMiscHandler.of(sig.iSignal, oldHandler); 160 } 161 162 /** 163 * Raises a signal in the current process. 164 * 165 * @param sig a signal 166 * @see sun.misc.Signal#handle(Signal sig, SignalHandler handler) 167 */ 168 public static void raise(Signal sig) throws IllegalArgumentException { 169 jdk.internal.misc.Signal.raise(sig.iSignal); 170 } 171 172 /* 173 * Wrapper class to proxy a SignalHandler to a jdk.internal.misc.Signal.Handler. 174 */ 175 static final class InternalMiscHandler implements jdk.internal.misc.Signal.Handler { 176 private final SignalHandler handler; 177 private final Signal signal; 178 179 static jdk.internal.misc.Signal.Handler of(Signal signal, SignalHandler handler) { 180 if (handler == SignalHandler.SIG_DFL) { 181 return jdk.internal.misc.Signal.Handler.SIG_DFL; 182 } else if (handler == SignalHandler.SIG_IGN) { 183 return jdk.internal.misc.Signal.Handler.SIG_IGN; 184 } else if (handler instanceof SunMiscHandler) { 185 return ((SunMiscHandler)handler).iHandler; 186 } else { 187 return new InternalMiscHandler(signal, handler); 188 } 189 } 190 191 private InternalMiscHandler(Signal signal, SignalHandler handler) { 192 this.handler = handler; 193 this.signal = signal; 194 } 195 196 @Override 197 public void handle(jdk.internal.misc.Signal ignore) { 198 handler.handle(signal); 199 } 200 } 201 202 /* 203 * Wrapper class to proxy a jdk.internal.misc.Signal.Handler to a SignalHandler. 204 */ 205 static final class SunMiscHandler implements SignalHandler { 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 } 235} 236