8149750: Decouple sun.misc.Signal from the base module
Reviewed-by: chegar, dholmes
This commit is contained in:
parent
0dd8a15d8d
commit
1ea7533dbf
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -244,10 +244,9 @@ SUNWprivate_1.1 {
|
||||
Java_java_util_TimeZone_getSystemTimeZoneID;
|
||||
Java_java_util_TimeZone_getSystemGMTOffsetID;
|
||||
Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8;
|
||||
Java_sun_misc_NativeSignalHandler_handle0;
|
||||
Java_sun_misc_Signal_findSignal;
|
||||
Java_sun_misc_Signal_handle0;
|
||||
Java_sun_misc_Signal_raise0;
|
||||
Java_jdk_internal_misc_Signal_findSignal0;
|
||||
Java_jdk_internal_misc_Signal_handle0;
|
||||
Java_jdk_internal_misc_Signal_raise0;
|
||||
Java_sun_reflect_ConstantPool_getClassAt0;
|
||||
Java_sun_reflect_ConstantPool_getClassAtIfLoaded0;
|
||||
Java_sun_reflect_ConstantPool_getClassRefIndexAt0;
|
||||
|
@ -35,8 +35,6 @@ text: .text%Java_sun_reflect_NativeConstructorAccessorImpl_newInstance0;
|
||||
text: .text%Java_java_lang_System_setOut0;
|
||||
text: .text%Java_java_lang_System_setErr0;
|
||||
text: .text%Java_java_lang_System_identityHashCode;
|
||||
text: .text%Java_sun_misc_Signal_findSignal;
|
||||
text: .text%Java_sun_misc_Signal_handle0;
|
||||
text: .text%JNU_NewObjectByName;
|
||||
text: .text%Java_java_io_UnixFileSystem_initIDs;
|
||||
text: .text%Java_java_io_UnixFileSystem_canonicalize0;
|
||||
|
@ -39,8 +39,6 @@ text: .text%Java_java_lang_Throwable_fillInStackTrace;
|
||||
text: .text%Java_java_lang_System_setOut0;
|
||||
text: .text%Java_java_lang_System_setErr0;
|
||||
text: .text%Java_java_lang_System_identityHashCode;
|
||||
text: .text%Java_sun_misc_Signal_findSignal;
|
||||
text: .text%Java_sun_misc_Signal_handle0;
|
||||
text: .text%JNU_NewObjectByName;
|
||||
text: .text%Java_java_io_UnixFileSystem_initIDs;
|
||||
text: .text%Java_java_io_UnixFileSystem_canonicalize0;
|
||||
|
@ -81,8 +81,6 @@ text: .text%Java_java_lang_reflect_Array_newArray;
|
||||
text: .text%Java_java_lang_Throwable_getStackTraceDepth;
|
||||
text: .text%Java_java_lang_Throwable_getStackTraceElement;
|
||||
text: .text%Java_java_lang_System_identityHashCode;
|
||||
text: .text%Java_sun_misc_Signal_findSignal;
|
||||
text: .text%Java_sun_misc_Signal_handle0;
|
||||
text: .text%JNU_NotifyAll;
|
||||
# Test LoadFrame
|
||||
text: .text%JNU_CallMethodByName;
|
||||
|
284
jdk/src/java.base/share/classes/jdk/internal/misc/Signal.java
Normal file
284
jdk/src/java.base/share/classes/jdk/internal/misc/Signal.java
Normal file
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.internal.misc;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This class provides ANSI/ISO C signal support. A Java program can register
|
||||
* signal handlers for the current process. There are two restrictions:
|
||||
* <ul>
|
||||
* <li>
|
||||
* Java code cannot register a handler for signals that are already used
|
||||
* by the Java VM implementation. The <code>Signal.handle</code>
|
||||
* function raises an <code>IllegalArgumentException</code> if such an attempt
|
||||
* is made.
|
||||
* <li>
|
||||
* When <code>Signal.handle</code> is called, the VM internally registers a
|
||||
* special C signal handler. There is no way to force the Java signal handler
|
||||
* to run synchronously before the C signal handler returns. Instead, when the
|
||||
* VM receives a signal, the special C signal handler creates a new thread
|
||||
* (at priority <code>Thread.MAX_PRIORITY</code>) to
|
||||
* run the registered Java signal handler. The C signal handler immediately
|
||||
* returns. Note that because the Java signal handler runs in a newly created
|
||||
* thread, it may not actually be executed until some time after the C signal
|
||||
* handler returns.
|
||||
* </ul>
|
||||
* <p>
|
||||
* Signal objects are created based on their names. For example:
|
||||
* <blockquote><pre>
|
||||
* new Signal("INT");
|
||||
* </pre></blockquote>
|
||||
* constructs a signal object corresponding to <code>SIGINT</code>, which is
|
||||
* typically produced when the user presses <code>Ctrl-C</code> at the command line.
|
||||
* The <code>Signal</code> constructor throws <code>IllegalArgumentException</code>
|
||||
* when it is passed an unknown signal.
|
||||
* <p>
|
||||
* This is an example of how Java code handles <code>SIGINT</code>:
|
||||
* <blockquote><pre>
|
||||
* Signal.Handler handler = new Signal.Handler () {
|
||||
* public void handle(Signal sig) {
|
||||
* ... // handle SIGINT
|
||||
* }
|
||||
* };
|
||||
* Signal.handle(new Signal("INT"), handler);
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
public final class Signal {
|
||||
private static Hashtable<Signal, Signal.Handler> handlers = new Hashtable<>(4);
|
||||
private static Hashtable<Integer, Signal> signals = new Hashtable<>(4);
|
||||
|
||||
private int number;
|
||||
private String name;
|
||||
|
||||
/* Returns the signal number */
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the signal name.
|
||||
*
|
||||
* @return the name of the signal.
|
||||
* @see jdk.internal.misc.Signal#Signal(String name)
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the equality of two <code>Signal</code> objects.
|
||||
*
|
||||
* @param other the object to compare with.
|
||||
* @return whether two <code>Signal</code> objects are equal.
|
||||
*/
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (other == null || !(other instanceof Signal)) {
|
||||
return false;
|
||||
}
|
||||
Signal other1 = (Signal)other;
|
||||
return name.equals(other1.name) && (number == other1.number);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hashcode for this Signal.
|
||||
*
|
||||
* @return a hash code value for this object.
|
||||
*/
|
||||
public int hashCode() {
|
||||
return number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a signal from its name.
|
||||
*
|
||||
* @param name the name of the signal.
|
||||
* @exception IllegalArgumentException unknown signal
|
||||
* @see jdk.internal.misc.Signal#getName()
|
||||
*/
|
||||
public Signal(String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
// Signal names are the short names;
|
||||
// the "SIG" prefix is not used for compatibility with previous JDKs
|
||||
if (name.startsWith("SIG")) {
|
||||
throw new IllegalArgumentException("Unknown signal: " + name);
|
||||
}
|
||||
this.name = name;
|
||||
number = findSignal0(name);
|
||||
if (number < 0) {
|
||||
throw new IllegalArgumentException("Unknown signal: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a signal handler.
|
||||
*
|
||||
* @param sig a signal
|
||||
* @param handler the handler to be registered with the given signal.
|
||||
* @return the old handler
|
||||
* @exception IllegalArgumentException the signal is in use by the VM
|
||||
* @see jdk.internal.misc.Signal#raise(Signal sig)
|
||||
* @see jdk.internal.misc.Signal.Handler
|
||||
* @see jdk.internal.misc.Signal.Handler#SIG_DFL
|
||||
* @see jdk.internal.misc.Signal.Handler#SIG_IGN
|
||||
*/
|
||||
public static synchronized Signal.Handler handle(Signal sig,
|
||||
Signal.Handler handler)
|
||||
throws IllegalArgumentException {
|
||||
Objects.requireNonNull(sig, "sig");
|
||||
Objects.requireNonNull(handler, "handler");
|
||||
long newH = (handler instanceof NativeHandler) ?
|
||||
((NativeHandler)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) {
|
||||
Signal.Handler oldHandler = handlers.get(sig);
|
||||
handlers.remove(sig);
|
||||
if (newH == 2) {
|
||||
handlers.put(sig, handler);
|
||||
}
|
||||
if (oldH == 0) {
|
||||
return Signal.Handler.SIG_DFL;
|
||||
} else if (oldH == 1) {
|
||||
return Signal.Handler.SIG_IGN;
|
||||
} else if (oldH == 2) {
|
||||
return oldHandler;
|
||||
} else {
|
||||
return new NativeHandler(oldH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Raises a signal in the current process.
|
||||
*
|
||||
* @param sig a signal
|
||||
* @see jdk.internal.misc.Signal#handle(Signal sig, Signal.Handler handler)
|
||||
*/
|
||||
public static void raise(Signal sig) throws IllegalArgumentException {
|
||||
Objects.requireNonNull(sig, "sig");
|
||||
if (handlers.get(sig) == null) {
|
||||
throw new IllegalArgumentException("Unhandled signal: " + sig);
|
||||
}
|
||||
raise0(sig.number);
|
||||
}
|
||||
|
||||
/* Called by the VM to execute Java signal handlers. */
|
||||
private static void dispatch(final int number) {
|
||||
final Signal sig = signals.get(number);
|
||||
final Signal.Handler 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();
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the signal number, given a name. Returns -1 for unknown signals. */
|
||||
private static native int findSignal0(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);
|
||||
|
||||
/**
|
||||
* This is the signal handler interface expected in <code>Signal.handle</code>.
|
||||
*/
|
||||
public interface Handler {
|
||||
|
||||
/**
|
||||
* The default signal handler
|
||||
*/
|
||||
public static final Signal.Handler SIG_DFL = new NativeHandler(0);
|
||||
/**
|
||||
* Ignore the signal
|
||||
*/
|
||||
public static final Signal.Handler SIG_IGN = new NativeHandler(1);
|
||||
|
||||
/**
|
||||
* Handle the given signal
|
||||
*
|
||||
* @param sig a signal object
|
||||
*/
|
||||
public void handle(Signal sig);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* A package-private class implementing a signal handler in native code.
|
||||
*/
|
||||
static final class NativeHandler implements Signal.Handler {
|
||||
|
||||
private final long handler;
|
||||
|
||||
long getHandler() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
NativeHandler(long handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public void handle(Signal sig) {
|
||||
throw new UnsupportedOperationException("invoking native signal handle not supported");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.misc;
|
||||
|
||||
/* A package-private class implementing a signal handler in native code. */
|
||||
|
||||
final class NativeSignalHandler implements SignalHandler {
|
||||
|
||||
private final long handler;
|
||||
|
||||
long getHandler() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
NativeSignalHandler(long handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public void handle(Signal sig) {
|
||||
handle0(sig.getNumber(), handler);
|
||||
}
|
||||
|
||||
private static native void handle0(int number, long handler);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,7 +24,8 @@
|
||||
*/
|
||||
|
||||
package sun.misc;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This class provides ANSI/ISO C signal support. A Java program can register
|
||||
@ -68,19 +69,17 @@ import java.util.Hashtable;
|
||||
*
|
||||
* @author Sheng Liang
|
||||
* @author Bill Shannon
|
||||
* @see sun.misc.SignalHandler
|
||||
* @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;
|
||||
// Delegate to jdk.internal.misc.Signal.
|
||||
private final jdk.internal.misc.Signal iSignal;
|
||||
|
||||
/* Returns the signal number */
|
||||
public int getNumber() {
|
||||
return number;
|
||||
return iSignal.getNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,7 +89,7 @@ public final class Signal {
|
||||
* @see sun.misc.Signal#Signal(String name)
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
return iSignal.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -107,7 +106,7 @@ public final class Signal {
|
||||
return false;
|
||||
}
|
||||
Signal other1 = (Signal)other;
|
||||
return name.equals(other1.name) && (number == other1.number);
|
||||
return iSignal.equals(other1.iSignal);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,7 +115,7 @@ public final class Signal {
|
||||
* @return a hash code value for this object.
|
||||
*/
|
||||
public int hashCode() {
|
||||
return number;
|
||||
return getNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,7 +125,7 @@ public final class Signal {
|
||||
* @return a string representation of the signal
|
||||
*/
|
||||
public String toString() {
|
||||
return "SIG" + name;
|
||||
return iSignal.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,11 +136,7 @@ public final class 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);
|
||||
}
|
||||
iSignal = new jdk.internal.misc.Signal(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -159,30 +154,9 @@ public final class Signal {
|
||||
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);
|
||||
}
|
||||
}
|
||||
jdk.internal.misc.Signal.Handler oldHandler = jdk.internal.misc.Signal.handle(sig.iSignal,
|
||||
InternalMiscHandler.of(sig, handler));
|
||||
return SunMiscHandler.of(sig.iSignal, oldHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -192,41 +166,70 @@ public final class Signal {
|
||||
* @see sun.misc.Signal#handle(Signal sig, SignalHandler handler)
|
||||
*/
|
||||
public static void raise(Signal sig) throws IllegalArgumentException {
|
||||
if (handlers.get(sig) == null) {
|
||||
throw new IllegalArgumentException("Unhandled signal: " + sig);
|
||||
}
|
||||
raise0(sig.number);
|
||||
jdk.internal.misc.Signal.raise(sig.iSignal);
|
||||
}
|
||||
|
||||
/* 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();
|
||||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
/*
|
||||
* Wrapper class to proxy a SignalHandler to a jdk.internal.misc.Signal.Handler.
|
||||
*/
|
||||
private static native long handle0(int sig, long nativeH);
|
||||
/* Raise a given signal number */
|
||||
private static native void raise0(int sig);
|
||||
static final class InternalMiscHandler implements jdk.internal.misc.Signal.Handler {
|
||||
private final SignalHandler handler;
|
||||
private final Signal signal;
|
||||
|
||||
static jdk.internal.misc.Signal.Handler of(Signal signal, SignalHandler handler) {
|
||||
if (handler == SignalHandler.SIG_DFL) {
|
||||
return jdk.internal.misc.Signal.Handler.SIG_DFL;
|
||||
} else if (handler == SignalHandler.SIG_IGN) {
|
||||
return jdk.internal.misc.Signal.Handler.SIG_IGN;
|
||||
} else if (handler instanceof SunMiscHandler) {
|
||||
return ((SunMiscHandler)handler).iHandler;
|
||||
} else {
|
||||
return new InternalMiscHandler(signal, handler);
|
||||
}
|
||||
}
|
||||
|
||||
private InternalMiscHandler(Signal signal, SignalHandler handler) {
|
||||
this.handler = handler;
|
||||
this.signal = signal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(jdk.internal.misc.Signal ignore) {
|
||||
handler.handle(signal);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper class to proxy a jdk.internal.misc.Signal.Handler to a SignalHandler.
|
||||
*/
|
||||
static final class SunMiscHandler implements SignalHandler {
|
||||
private final jdk.internal.misc.Signal iSignal;
|
||||
private final jdk.internal.misc.Signal.Handler iHandler;
|
||||
|
||||
static SignalHandler of(jdk.internal.misc.Signal signal, jdk.internal.misc.Signal.Handler handler) {
|
||||
if (handler == jdk.internal.misc.Signal.Handler.SIG_DFL) {
|
||||
return SignalHandler.SIG_DFL;
|
||||
} else if (handler == jdk.internal.misc.Signal.Handler.SIG_IGN) {
|
||||
return SignalHandler.SIG_IGN;
|
||||
} else if (handler instanceof InternalMiscHandler) {
|
||||
return ((InternalMiscHandler) handler).handler;
|
||||
} else {
|
||||
return new SunMiscHandler(signal, handler);
|
||||
}
|
||||
}
|
||||
|
||||
SunMiscHandler(jdk.internal.misc.Signal iSignal, jdk.internal.misc.Signal.Handler iHandler) {
|
||||
this.iSignal = iSignal;
|
||||
this.iHandler = iHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Signal sig) {
|
||||
iHandler.handle(iSignal);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return iHandler.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,11 +39,13 @@ public interface SignalHandler {
|
||||
/**
|
||||
* The default signal handler
|
||||
*/
|
||||
public static final SignalHandler SIG_DFL = new NativeSignalHandler(0);
|
||||
public static final SignalHandler SIG_DFL =
|
||||
new Signal.SunMiscHandler(null, jdk.internal.misc.Signal.Handler.SIG_DFL);
|
||||
/**
|
||||
* Ignore the signal
|
||||
*/
|
||||
public static final SignalHandler SIG_IGN = new NativeSignalHandler(1);
|
||||
public static final SignalHandler SIG_IGN =
|
||||
new Signal.SunMiscHandler(null, jdk.internal.misc.Signal.Handler.SIG_IGN);
|
||||
|
||||
/**
|
||||
* Handle the given signal
|
||||
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <jni.h>
|
||||
#include <jlong.h>
|
||||
#include "sun_misc_NativeSignalHandler.h"
|
||||
|
||||
typedef void (*sig_handler_t)(jint, void *, void *);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_misc_NativeSignalHandler_handle0(JNIEnv *env, jclass cls, jint sig, jlong f)
|
||||
{
|
||||
/* We've lost the siginfo and context */
|
||||
(*(sig_handler_t)jlong_to_ptr(f))(sig, NULL, NULL);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,13 +30,18 @@
|
||||
#include <jvm.h>
|
||||
#include <jni_util.h>
|
||||
#include <jlong.h>
|
||||
#include "sun_misc_Signal.h"
|
||||
#include "jdk_internal_misc_Signal.h"
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_misc_Signal_findSignal(JNIEnv *env, jclass cls, jstring name)
|
||||
Java_jdk_internal_misc_Signal_findSignal0(JNIEnv *env, jclass cls, jstring name)
|
||||
{
|
||||
jint res;
|
||||
const char *cname = (*env)->GetStringUTFChars(env, name, 0);
|
||||
const char *cname;
|
||||
if (name == NULL) {
|
||||
JNU_ThrowNullPointerException(env, "name");
|
||||
return 0;
|
||||
}
|
||||
cname = (*env)->GetStringUTFChars(env, name, 0);
|
||||
if (cname == NULL) {
|
||||
/* out of memory thrown */
|
||||
return 0;
|
||||
@ -47,13 +52,13 @@ Java_sun_misc_Signal_findSignal(JNIEnv *env, jclass cls, jstring name)
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_sun_misc_Signal_handle0(JNIEnv *env, jclass cls, jint sig, jlong handler)
|
||||
Java_jdk_internal_misc_Signal_handle0(JNIEnv *env, jclass cls, jint sig, jlong handler)
|
||||
{
|
||||
return ptr_to_jlong(JVM_RegisterSignal(sig, jlong_to_ptr(handler)));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_misc_Signal_raise0(JNIEnv *env, jclass cls, jint sig)
|
||||
Java_jdk_internal_misc_Signal_raise0(JNIEnv *env, jclass cls, jint sig)
|
||||
{
|
||||
JVM_RaiseSignal(sig);
|
||||
}
|
||||
|
@ -25,8 +25,7 @@
|
||||
|
||||
package java.lang;
|
||||
|
||||
import sun.misc.Signal;
|
||||
import sun.misc.SignalHandler;
|
||||
import jdk.internal.misc.Signal;
|
||||
|
||||
|
||||
/**
|
||||
@ -39,7 +38,7 @@ import sun.misc.SignalHandler;
|
||||
|
||||
class Terminator {
|
||||
|
||||
private static SignalHandler handler = null;
|
||||
private static Signal.Handler handler = null;
|
||||
|
||||
/* Invocations of setup and teardown are already synchronized
|
||||
* on the shutdown lock, so no further synchronization is needed here
|
||||
@ -47,7 +46,7 @@ class Terminator {
|
||||
|
||||
static void setup() {
|
||||
if (handler != null) return;
|
||||
SignalHandler sh = new SignalHandler() {
|
||||
Signal.Handler sh = new Signal.Handler() {
|
||||
public void handle(Signal sig) {
|
||||
Shutdown.exit(sig.getNumber() + 0200);
|
||||
}
|
||||
|
@ -25,8 +25,7 @@
|
||||
|
||||
package java.lang;
|
||||
|
||||
import sun.misc.Signal;
|
||||
import sun.misc.SignalHandler;
|
||||
import jdk.internal.misc.Signal;
|
||||
|
||||
|
||||
/**
|
||||
@ -39,7 +38,7 @@ import sun.misc.SignalHandler;
|
||||
|
||||
class Terminator {
|
||||
|
||||
private static SignalHandler handler = null;
|
||||
private static Signal.Handler handler = null;
|
||||
|
||||
/* Invocations of setup and teardown are already synchronized
|
||||
* on the shutdown lock, so no further synchronization is needed here
|
||||
@ -47,7 +46,7 @@ class Terminator {
|
||||
|
||||
static void setup() {
|
||||
if (handler != null) return;
|
||||
SignalHandler sh = new SignalHandler() {
|
||||
Signal.Handler sh = new Signal.Handler() {
|
||||
public void handle(Signal sig) {
|
||||
Shutdown.exit(sig.getNumber() + 0200);
|
||||
}
|
||||
|
398
jdk/test/sun/misc/SunMiscSignalTest.java
Normal file
398
jdk/test/sun/misc/SunMiscSignalTest.java
Normal file
@ -0,0 +1,398 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.testng.Assert;
|
||||
import org.testng.TestNG;
|
||||
import org.testng.annotations.Test;
|
||||
import org.testng.annotations.BeforeSuite;
|
||||
import org.testng.annotations.DataProvider;
|
||||
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.Utils;
|
||||
|
||||
import sun.misc.Signal;
|
||||
import sun.misc.SignalHandler;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @library /test/lib/share/classes
|
||||
* @build jdk.test.lib.Platform jdk.test.lib.Utils
|
||||
* @run testng/othervm -Xrs -DXrs=true SunMiscSignalTest
|
||||
* @run testng/othervm SunMiscSignalTest
|
||||
* @summary sun.misc.Signal test
|
||||
*/
|
||||
|
||||
@Test
|
||||
public class SunMiscSignalTest {
|
||||
|
||||
// Set to true to enable additional debug output
|
||||
static boolean debug = true;
|
||||
|
||||
// True to test while running with -Xrs
|
||||
static boolean RUNNING_WITH_Xrs = Boolean.getBoolean("Xrs");
|
||||
|
||||
/**
|
||||
* Print a debug message if enabled.
|
||||
*
|
||||
* @param format the format
|
||||
* @param args the arguments
|
||||
*/
|
||||
static void printf(String format, Object... args) {
|
||||
if (debug) {
|
||||
System.out.printf(" " + format, args);
|
||||
}
|
||||
}
|
||||
|
||||
enum IsSupported {NO, YES}
|
||||
|
||||
enum CanRegister {NO, YES}
|
||||
|
||||
enum CanRaise {NO, YES}
|
||||
|
||||
enum Invoked {NO, YES}
|
||||
|
||||
enum RestrictedSignals {NORMAL, XRS}
|
||||
|
||||
@BeforeSuite
|
||||
static void setup() {
|
||||
System.out.printf("-Xrs: %s%n", RUNNING_WITH_Xrs);
|
||||
}
|
||||
|
||||
// Provider of signals to be tested with variations for -Xrs and
|
||||
// platform dependencies
|
||||
// -Xrs restricted signals signals the VM will not handle SIGINT, SIGTERM, SIGHUP and others
|
||||
@DataProvider(name = "supportedSignals")
|
||||
static Object[][] supportedSignals() {
|
||||
RestrictedSignals rs = RUNNING_WITH_Xrs ? RestrictedSignals.XRS : RestrictedSignals.NORMAL;
|
||||
CanRegister registerXrs = RUNNING_WITH_Xrs ? CanRegister.NO : CanRegister.YES;
|
||||
CanRaise raiseXrs = RUNNING_WITH_Xrs ? CanRaise.NO : CanRaise.YES;
|
||||
Invoked invokedXrs = RUNNING_WITH_Xrs ? Invoked.NO : Invoked.YES;
|
||||
|
||||
Object[][] commonSignals = new Object[][]{
|
||||
{"INT", IsSupported.YES, registerXrs, raiseXrs, invokedXrs},
|
||||
{"TERM", IsSupported.YES, registerXrs, raiseXrs, invokedXrs},
|
||||
{"ABRT", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
};
|
||||
|
||||
Object[][] posixSignals = {
|
||||
{"HUP", IsSupported.YES, registerXrs, raiseXrs, invokedXrs},
|
||||
{"QUIT", IsSupported.YES, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"BUS", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"USR1", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"USR2", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"PIPE", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"ALRM", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"CHLD", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"CONT", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"TSTP", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"TTIN", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"TTOU", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"URG", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"XCPU", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"XFSZ", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"VTALRM", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"PROF", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"WINCH", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"IO", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
{"SYS", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
|
||||
};
|
||||
|
||||
Object[][] windowsSignals = {
|
||||
{"HUP", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"QUIT", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"BUS", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"USR1", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"USR2", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"PIPE", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"ALRM", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"CHLD", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"CONT", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"TSTP", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"TTIN", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"TTOU", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"URG", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"XCPU", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"XFSZ", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"VTALRM", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"PROF", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"WINCH", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"IO", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
{"SYS", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
|
||||
};
|
||||
|
||||
return concatArrays(commonSignals, (Platform.isWindows() ? windowsSignals : posixSignals));
|
||||
}
|
||||
|
||||
// Provider of invalid signal names
|
||||
@DataProvider(name = "invalidSunMiscSignalNames")
|
||||
Object[][] invalidSunMiscSignalNames() {
|
||||
return new Object[][]{
|
||||
{""},
|
||||
{"I"},
|
||||
{"SIG"},
|
||||
{"SIGabc"},
|
||||
{"SIGINT"}, // prefix not allowed
|
||||
{"abc"},
|
||||
};
|
||||
}
|
||||
|
||||
static Object[][] concatArrays(Object[][]... arrays) {
|
||||
int l = 0;
|
||||
for (Object[][] a : arrays) {
|
||||
l += a.length;
|
||||
}
|
||||
|
||||
Object[][] newArray = new Object[l][];
|
||||
l = 0;
|
||||
for (int i = 0; i < arrays.length; i++) {
|
||||
System.arraycopy(arrays[i], 0, newArray, l, arrays[i].length);
|
||||
l += arrays[i].length;
|
||||
}
|
||||
|
||||
return newArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick verification of supported signals using sun.misc.Signal.
|
||||
*
|
||||
* @param name the signal name
|
||||
* @throws InterruptedException would be an error if thrown
|
||||
*/
|
||||
@Test(dataProvider = "supportedSignals")
|
||||
static void testSunMisc(String name, IsSupported supported, CanRegister register,
|
||||
CanRaise raise, Invoked invoked) throws InterruptedException {
|
||||
Handler h = new Handler();
|
||||
SignalHandler orig = null;
|
||||
Signal signal = null;
|
||||
try {
|
||||
signal = new Signal(name);
|
||||
Assert.assertEquals(supported, IsSupported.YES, "Unexpected support for " + name);
|
||||
|
||||
Assert.assertEquals(signal.getName(), name, "getName() mismatch, ");
|
||||
|
||||
Assert.assertEquals(signal.toString(), "SIG" + name, "toString() mismatch, ");
|
||||
|
||||
try {
|
||||
SignalHandler old = Signal.handle(signal, h);
|
||||
Assert.assertEquals(CanRegister.YES, register, "Unexpected handle succeeded " + name);
|
||||
try {
|
||||
Signal.raise(signal);
|
||||
Assert.assertEquals(CanRaise.YES, raise, "Unexpected raise success for " + name);
|
||||
Invoked inv = h.semaphore().tryAcquire(Utils.adjustTimeout(100L),
|
||||
TimeUnit.MILLISECONDS) ? Invoked.YES : Invoked.NO;
|
||||
Assert.assertEquals(inv, invoked, "handler not invoked;");
|
||||
} catch (IllegalArgumentException uoe3) {
|
||||
Assert.assertNotEquals(CanRaise.YES, raise, "raise failed for " + name +
|
||||
": " + uoe3.getMessage());
|
||||
}
|
||||
} catch (IllegalArgumentException uoe2) {
|
||||
Assert.assertNotEquals(CanRegister.YES, register, "handle failed for: " + name +
|
||||
": " + uoe2.getMessage());
|
||||
}
|
||||
} catch (IllegalArgumentException uoe) {
|
||||
Assert.assertNotEquals(IsSupported.YES, supported, "Support missing for " + name +
|
||||
": " + uoe.getMessage());
|
||||
return;
|
||||
} finally {
|
||||
// Restore original signal handler
|
||||
if (orig != null && signal != null) {
|
||||
Signal.handle(signal, orig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test Signal is equal to itself and not equals to others
|
||||
@Test(dataProvider = "supportedSignals")
|
||||
static void testEquals(String name, IsSupported supported, CanRegister register,
|
||||
CanRaise raise, Invoked invoked) {
|
||||
Object[][] data = supportedSignals();
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
IsSupported otherSupported = (IsSupported) data[i][1];
|
||||
if (supported == IsSupported.NO || otherSupported == IsSupported.NO) {
|
||||
continue;
|
||||
}
|
||||
String otherName = (String) data[i][0];
|
||||
|
||||
Signal sig1 = new Signal(name);
|
||||
Signal sig2 = new Signal(otherName);
|
||||
if (name.equals(otherName)) {
|
||||
Assert.assertEquals(sig1, sig2, "Equals failed; ");
|
||||
Assert.assertEquals(sig1.hashCode(), sig2.hashCode(), "HashCode wrong; ");
|
||||
} else {
|
||||
Assert.assertNotEquals(sig1, sig2, "NotEquals failed; ");
|
||||
Assert.assertNotEquals(sig1.hashCode(), sig2.hashCode(), "HashCode wrong; ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "invalidSunMiscSignalNames")
|
||||
static void testSunMiscIAE(String name) {
|
||||
try {
|
||||
new Signal(name);
|
||||
Assert.fail("Should have thrown IAE for signal: " + name);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
Assert.assertEquals(iae.getMessage(), "Unknown signal: " + name, "getMessage() incorrect; ");
|
||||
}
|
||||
}
|
||||
|
||||
// Note: JDK 8 did not check/throw NPE, passing null resulted in a segv
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
static void nullSignal() {
|
||||
new Signal(null);
|
||||
}
|
||||
|
||||
// Test expected exception when raising a signal when no handler defined
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
static void testRaiseNoConsumer() {
|
||||
Signal signal = new Signal("INT");
|
||||
SignalHandler orig = null;
|
||||
try {
|
||||
Signal.handle(signal, SignalHandler.SIG_DFL);
|
||||
Signal.raise(signal);
|
||||
} finally {
|
||||
// Restore original signal handler
|
||||
if (orig != null && signal != null) {
|
||||
Signal.handle(signal, orig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The thread that runs the handler for sun.misc.Signal should be a
|
||||
* Daemon thread.
|
||||
*/
|
||||
@Test
|
||||
static void isDaemonThread() throws InterruptedException {
|
||||
if (RUNNING_WITH_Xrs) {
|
||||
return;
|
||||
}
|
||||
Handler handler = new Handler();
|
||||
Signal signal = new Signal("INT");
|
||||
Signal.handle(signal, handler);
|
||||
Signal.raise(signal);
|
||||
boolean handled = handler.semaphore()
|
||||
.tryAcquire(Utils.adjustTimeout(100L), TimeUnit.MILLISECONDS);
|
||||
Assert.assertEquals(handled, !RUNNING_WITH_Xrs,
|
||||
"raising s.m.Signal did not get a callback;");
|
||||
|
||||
Assert.assertTrue(handler.wasDaemon(), "Thread.isDaemon running the handler; ");
|
||||
}
|
||||
|
||||
// Check that trying to invoke SIG_DFL.handle throws UnsupportedOperationException.
|
||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
||||
static void cannotHandleSIGDFL() {
|
||||
Signal signal = new Signal("INT");
|
||||
Assert.assertNotNull(SignalHandler.SIG_DFL, "SIG_DFL null; ");
|
||||
SignalHandler.SIG_DFL.handle(signal);
|
||||
}
|
||||
|
||||
// Check that trying to invoke SIG_IGN.handle throws UnsupportedOperationException.
|
||||
@Test(expectedExceptions = UnsupportedOperationException.class)
|
||||
static void cannotHandleSIGIGN() {
|
||||
Signal signal = new Signal("INT");
|
||||
Assert.assertNotNull(SignalHandler.SIG_IGN, "SIG_IGN null; ");
|
||||
SignalHandler.SIG_IGN.handle(signal);
|
||||
}
|
||||
|
||||
// Check that setting a Signal handler returns the previous handler.
|
||||
@Test()
|
||||
static void checkLastHandler() {
|
||||
if (RUNNING_WITH_Xrs) {
|
||||
return;
|
||||
}
|
||||
Signal signal = new Signal("TERM");
|
||||
Handler h1 = new Handler();
|
||||
Handler h2 = new Handler();
|
||||
SignalHandler orig = Signal.handle(signal, h1);
|
||||
|
||||
try {
|
||||
SignalHandler prev = Signal.handle(signal, h2);
|
||||
Assert.assertSame(prev, h1, "prev handler mismatch");
|
||||
|
||||
prev = Signal.handle(signal, h1);
|
||||
Assert.assertSame(prev, h2, "prev handler mismatch");
|
||||
} finally {
|
||||
if (orig != null && signal != null) {
|
||||
Signal.handle(signal, orig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Handler, a SignalHandler for Signal notifications.
|
||||
* Signals a semaphore when invoked and records whether
|
||||
* the thread calling the Handler was a daemon.
|
||||
*/
|
||||
static class Handler implements SignalHandler {
|
||||
// A semaphore to check for accept being called
|
||||
Semaphore sema = new Semaphore(0);
|
||||
|
||||
Boolean wasDaemon = null;
|
||||
|
||||
Semaphore semaphore() {
|
||||
return sema;
|
||||
}
|
||||
|
||||
synchronized Boolean wasDaemon() {
|
||||
return wasDaemon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the semaphore when called as SignalHandler.handle.
|
||||
*
|
||||
* @param signal the Signal that occurred
|
||||
*/
|
||||
@Override
|
||||
public void handle(Signal signal) {
|
||||
synchronized (this) {
|
||||
wasDaemon = Thread.currentThread().isDaemon();
|
||||
}
|
||||
sema.release();
|
||||
printf("sun.misc.handle sig: %s, num: %d%n", signal.getName(), signal.getNumber());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Handler: sem: " + sema.getQueueLength() +
|
||||
", wasDaemon: " + Objects.toString(wasDaemon());
|
||||
}
|
||||
}
|
||||
|
||||
// Main can be used to run the tests from the command line with only testng.jar.
|
||||
@SuppressWarnings("raw_types")
|
||||
@Test(enabled = false)
|
||||
public static void main(String[] args) {
|
||||
Class<?>[] testclass = {SunMiscSignalTest.class};
|
||||
TestNG testng = new TestNG();
|
||||
testng.setTestClasses(testclass);
|
||||
testng.run();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user