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