Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4345157
Votes 3
Synopsis JDK 1.3.0 alters thread signal mask
Category hotspot:runtime_system
Reported Against 1.3
Release Fixed 1.3.0_02, 1.3.1(ladybird-beta) (Bug ID:2034772) , 1.4(merlin-beta) (Bug ID:2034773)
State 10-Fix Delivered, Verified, bug
Priority: 2-High
Related Bugs 4363638 , 4381843 , 4381444 , 4390200 , 4411392 , 4440232 , 4739594
Submit Date 13-JUN-2000
Description




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
 customer  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) 
======================================================================
Work Around




None.
======================================================================
Evaluation
  xxxxx@xxxxx   2000-10-02: The change described in "Comments"
fixed the problem that iWS was having (according to Krishna Ramachandran).
An analogous change works for the program included in the "Description" section.

We are working on evolving an interface to allow the proper sharing of
signals between the JVM and an embedding program or native methods.

The change will be officially put back soon.

  xxxxx@xxxxx   2000-11-06: Robert and Ken, whenever the change has
been completed for Linux & Win32, the java -X message should be updated:

src/share/vm/Xusage.txt

with something along these lines:

   -Xrs      reduce usage of OS signals by Java/VM


By the way, at that time, placing the -X messages in alphabetic order
may seem to be a good thing to do, as well?

----
Ported over Solaris changes by   xxxxx@xxxxx   to Linux. Win32 changes were
done and closed under bug 4323062.

  xxxxx@xxxxx   2000-12-04
Comments
  
  Include a link with my name & email   

Submitted On 23-MAY-2001
john_basrai
I tried this with Solaris 2.7 both with 1.2.2_05a and
1.3.0-RC
and seems some other thread always gets the signal.  I was
using -Xrs
option which tells VM to leave SIGTERM alone yet dbx some VM
thread
was picked to handle the signal.

In my case I can't do this in main because I'm loading the
VM under
IPlanet 4.1 as a plugin.

SunOS replsrv1 5.7 Generic_106541-12 sun4u sparc
SUNW,Ultra-5_10



PLEASE NOTE: JDK6 is formerly known as Project Mustang