8149750: Decouple sun.misc.Signal from the base module

Reviewed-by: chegar, dholmes
This commit is contained in:
Roger Riggs 2016-02-18 14:44:50 -05:00
parent 0dd8a15d8d
commit 1ea7533dbf
13 changed files with 786 additions and 190 deletions

View File

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

View File

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

View File

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

View File

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

View 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");
}
}
}

View File

@ -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);
}

View File

@ -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();
}
}
}

View File

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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View 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();
}
}