Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-2034773 | 1.4.0 | Kenneth Russell | P2 | Closed | Fixed | beta |
JDK-2034772 | 1.3.1 | Kenneth Russell | P2 | Closed | Fixed | beta |
Name: rlT66838 Date: 06/13/2000
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-beta)
Java HotSpot(TM) Client VM (build 1.3-beta, mixed mode)
I have a problem with signals on JDK 1.3.0 beta on Solaris 7 using
the Hostpot VM (both client and server). When a thread attaches to the JVM
it seems that its signal mask is changed. This did not happen with JDK
1.2.2 on Solaris nor does it happen with Sun JDK 1.3.0 beta on Linux or
IBM JDK 1.3.0 alpha on Linux. So, I consider this to be a bug in JDK 1.3.0
beta on Solaris.
Please find attached a program to reproduce this. It will run a
long loop. Hitting Ctrl-C will interrupt the program. On Solaris JDK 1.3
this will happen abruptly, because a thread other than main will get the
signal. On any other JDK, the main thread will exit with a message.
On the machine tested uname -a gives:
SunOS sunsite.pub.ro 5.7 Generic_106541-11 sun4u sparc SUNW,Ultra-Enterprise
Dummy Java class to call from native code:
public class Prog
{
public static void main(String args[])
{
for(int i=1; i<1000000; i++)
System.out.println("Java class invoked: " + args[0] + " -> " + i);
}
}
C program:
#include <jni.h>
#include <dlfcn.h>
#include <pthread.h>
#include <signal.h>
#include <errno.h>
void *handle;
char* error;
jint (JNICALL *jni_create_java_vm)(JavaVM **, JNIEnv **, void *) = NULL;
JavaVM *jvm;
void loadJVM()
{
handle = dlopen(JVM_SO, RTLD_NOW|RTLD_GLOBAL);
if (!handle) {
fputs (dlerror(), stderr);
fputs (" : 2\n", stderr);
exit(1);
}
fputs("Will load JVM...\n", stderr);
jni_create_java_vm = dlsym(handle, "JNI_CreateJavaVM");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
fputs (" : 3\n", stderr);
exit(1);
}
fputs("JVM loaded okay.\n", stderr);
}
JNIEnv* initJVM() /* The JDK1.2 way of doing it */
{
JNIEnv *env = NULL;
JavaVMInitArgs vm_args;
JavaVMOption options[1];
jint res;
options[0].optionString = "-Djava.class.path=."; /* user classes */
vm_args.version = JNI_VERSION_1_2;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_FALSE;
fputs("Will create JVM...\n", stderr);
res = (*jni_create_java_vm)(&jvm, &env, &vm_args);
if (res < 0) {
fprintf(stderr, "Can't create Java VM: %d\n", res);
exit(1);
}
fputs("JVM created OK!\n", stderr);
return env;
}
void doStuff(JNIEnv *env)
{
jclass cls;
jmethodID mid;
jstring jstr;
jobjectArray args;
cls = (*env)->FindClass(env, "Prog");
if (cls == 0) {
fprintf(stderr, "Can't find Prog class\n");
exit(1);
}
mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
if (mid == 0) {
fprintf(stderr, "Can't find Prog.main\n");
exit(1);
}
jstr = (*env)->NewStringUTF(env, "from C!");
if (jstr == 0) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
args = (*env)->NewObjectArray(env, 1,
(*env)->FindClass(env, "java/lang/String"), jstr);
if (args == 0) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
(*env)->CallStaticVoidMethod(env, cls, mid, args);
}
JNIEnv* atchJVM()
{
JNIEnv *env = NULL;
int res;
res = (*jvm)->AttachCurrentThread(jvm, (void**)&env, NULL);
if (res < 0) {
fprintf(stderr, "Thread attach failed\n");
return NULL;
}
return env;
}
void* somethr(void* x)
{
JNIEnv *env;
fprintf(stderr, "Some thread will create JVM.\n");
loadJVM();
env = initJVM();
fprintf(stderr, "Some thread will call Java.\n");
doStuff(env);
if((*jvm)->DetachCurrentThread(jvm) != 0)
fputs("Error: thread not detached!\n", stderr);
fprintf(stderr, "Some thread exiting.\n");
return env;
}
int main()
{
JNIEnv *env;
sigset_t set;
pthread_t thr1;
pthread_attr_t attr;
int ss=0, sig;
fprintf(stderr, "Main thread will set signal mask.\n");
sigemptyset(&set);
sigaddset(&set, SIGPIPE);
sigaddset(&set, SIGTERM);
sigaddset(&set, SIGHUP);
sigaddset(&set, SIGINT);
pthread_sigmask(SIG_BLOCK, &set, NULL);
pthread_attr_init(&attr);
ss = 1024 * 1024;
pthread_attr_setstacksize(&attr, ss);
pthread_attr_getstacksize(&attr, &ss);
fprintf(stderr, "Stack size: %d\n", ss);
pthread_create(&thr1,NULL,somethr,NULL);
sigemptyset(&set);
sigaddset(&set, SIGTERM);
sigaddset(&set, SIGHUP);
sigaddset(&set, SIGINT);
fprintf(stderr, "Main thread waiting for signal.\n");
do {
int err;
sig = 0;
err = sigwait(&set, &sig);
if (err != 0 && err != EINTR) {
fprintf(stderr, "main: sigwait() error: %s\n", strerror(err));
}
else {
fprintf(stderr, "main: sigwait() got: %d\n", sig);
exit(0);
}
} while (sig != SIGTERM && sig != SIGINT);
pthread_join(thr1,
NULL);
dlclose(handle);
fputs("Main thread exiting.\n", stderr);
}
(Review ID: 106080)
======================================================================
- backported by
-
JDK-2034772 JDK 1.3.0 alters thread signal mask
- Closed
-
JDK-2034773 JDK 1.3.0 alters thread signal mask
- Closed
- relates to
-
JDK-4381444 Need to update documentation to reflect new semantics of -Xrs
- Resolved
-
JDK-4739594 JVM_handle_solaris_signal calling unknown userland routine when handling SIGPIPE
- Closed
-
JDK-4363638 Program hangs during creation of Java VM, if used with native DB interface.
- Closed
-
JDK-4411392 JNI app dies with "Internal Error" in JNI_CreateVM
- Closed
-
JDK-4381843 Should use "signal-chaining" when replacing user signal handlers in JVM
- Closed