dist: RedHat 6.1
kernel: 2.2.13
jdk: Blackdown 1.2.2RC3
glibc: 2.1.2-11

My story so far:

I use the invocation api to load the jvm and run some java code.  If the
thread I use to run the code is the main thread, everything works fine. 
If I create a thread (pthread_create) to run the code, I get a segv when
that thread exits.  This code runs fine on every Solaris or win32 (1.1
or 1.2) jvm that I've tried.  I am aware that there are problems with
using the green thread version with the invocation api, but to the best
of my knowledge I am using native threads.

To demonstrate the problem, I modified jdk1.2.2/src/launcher/java.c to
take a "-createthread" flag, which runs the java code in a new thread:

[chrisc@new-joker launcher]$ ./java Hello
Hello.
[chrisc@new-joker launcher]$ ./java -createthread Hello
Hello.
SIGSEGV   11*  segmentation violation

Full thread dump Classic VM (Linux_JDK_RC3, native threads):
    "Finalizer" (TID:0x2b90e320, sys_thread_t:0x80d0dc8, state:CW,
native ID:0xc04) prio=8
        at java.lang.Object.wait(Native Method)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:112)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:127)
        at
java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:174)
    "Reference Handler" (TID:0x2b90e3b0, sys_thread_t:0x80caa50,
state:CW, native ID:0x803) prio=10
        at java.lang.Object.wait(Native Method)
        at java.lang.Object.wait(Object.java:424)
        at
java.lang.ref.Reference$ReferenceHandler.run(Reference.java:114)
    "SIGQUIT handler" (TID:0x2b90e3e0, sys_thread_t:0x80d0290, state:R,
native ID:0x402) prio=5
    "main" (TID:0x2b90e1e0, sys_thread_t:0x80536c8, state:R, native
ID:0x400) prio=5
Monitor Cache Dump:
    java.lang.ref.ReferenceQueue$Lock@2B90E338/2B944028: <unowned>
        Waiting to be notified:
            "Finalizer" (0x80d0dc8)
    java.lang.ref.Reference$Lock@2B90E3C0/2B943B20: <unowned>
        Waiting to be notified:
            "Reference Handler" (0x80caa50)
Registered Monitor Dump:
    PCMap lock: <unowned>
    utf8 hash table: <unowned>
    JNI pinning lock: <unowned>
    JNI global reference lock: <unowned>
    BinClass lock: <unowned>
    Class linking lock: <unowned>
    System class loader lock: <unowned>
    Code rewrite lock: <unowned>
    Heap lock: <unowned>
    Monitor cache lock: <unowned>
    Thread queue lock: <unowned>

Under gdb, I see that the crash is in pthread_exit in the thread which I
created that ran the java code:

(gdb) where
#0  0x8126773 in ?? ()
#1  0x2aacb6e9 in pthread_exit (retval=0x0) at join.c:35
#2  0x2aacbed0 in pthread_allocate_stack (attr=0x7f1ffe60, 
    default_new_thread=0x7f3ffe60, pagesize=716003008,
out_new_thread=0x0, 
    out_new_thread_bottom=0x0, out_guardaddr=0x1005,
out_guardsize=0x46db)
    at manager.c:216
(gdb) info thr
* 6 Thread 18139  0x8126773 in ?? ()
  5 Thread 18138  0x2ab6358b in __sigsuspend (set=0x7f3ff93c)
    at ../sysdeps/unix/sysv/linux/sigsuspend.c:48
  4 Thread 18137  0x2ab6358b in __sigsuspend (set=0x7f5ff93c)
    at ../sysdeps/unix/sysv/linux/sigsuspend.c:48
  3 Thread 18136  0x2ab6358b in __sigsuspend (set=0x7f7ffae0)
    at ../sysdeps/unix/sysv/linux/sigsuspend.c:48
  2 Thread 18134 (initial thread)  0x2ab6358b in __sigsuspend
(set=0x7ffffa14)
    at ../sysdeps/unix/sysv/linux/sigsuspend.c:48
  1 Thread 18135 (manager thread)  0x2abef320 in __poll (fds=0x80d3d90, 
    nfds=1, timeout=2000) at ../sysdeps/unix/sysv/linux/poll.c:45

To reproduce the problem:

* Extract the source from /usr/local/jdk1.2.2/src.jar using "jar xvf
src.jar"

* cd src/launcher

* Patch java.c with the included diffs.

* Compile the launcher ("java") using:

$(CC) -g -Wall -L/usr/local/jdk1.2.2/jre/lib/i386/classic
-I/usr/local/jdk1.2.2/include -I/usr/local/jdk1.2.2/include/linux
-D_GNU_SOURCE -D_REENTRANT=1 java.c java_md.c -o java -ldl -lpthread
-ljvm

(I used egcs.)

* Run as above.

Any insights/guesses/suggestions would be greatly appreciated.  At this
point, I'll probably attempt to build the jdk from the source using the
Blackdown patches.

Thanks,
Chris

*** java.c      Sat Jan  1 16:30:32 2000
--- javax.c     Sat Jan  1 19:45:27 2000
***************
*** 29,34 ****
--- 29,35 ----
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
+ #include <pthread.h>
  
  #include <jni.h>
  #include "java.h"
***************
*** 38,43 ****
--- 39,45 ----
  #endif
  
  static jboolean printVersion = JNI_FALSE;
+ static jboolean createThread = JNI_FALSE;
  static char *progname;
  jboolean debug = JNI_FALSE;
  
***************
*** 75,96 ****
  /*
   * Entry point.
   */
  int
! main(int argc, char **argv)
  {
-     JavaVM *vm = 0;
      JNIEnv *env = 0;
-     char *jarfile = 0;
-     char *classname = 0;
      char *s = 0;
-     jclass mainClass;
-     jmethodID mainID;
-     jobjectArray mainArgs;
-     int ret;
      InvocationFunctions ifn;
      char *jvmtype = 0;
      jboolean jvmspecified = JNI_FALSE;     /* Assume no option
specified. */
      jlong start, end;
  
      if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) {
        debug = JNI_TRUE;
--- 77,100 ----
  /*
   * Entry point.
   */
+ int argc;
+ char **argv;
+ JavaVM *vm = 0;
+ char *jarfile = 0;
+ char *classname = 0;
+ 
  int
! initialize_vm(jboolean *prun)
  {
      JNIEnv *env = 0;
      char *s = 0;
      InvocationFunctions ifn;
      char *jvmtype = 0;
      jboolean jvmspecified = JNI_FALSE;     /* Assume no option
specified. */
      jlong start, end;
+     int ret;
+ 
+     *prun = JNI_FALSE;
  
      if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) {
        debug = JNI_TRUE;
***************
*** 110,116 ****
      }
      ifn.CreateJavaVM = 0; ifn.GetDefaultJavaVMInitArgs = 0;
      if (!LoadJavaVM(jvmtype, &ifn))
!       return 1;
  
      /* Grab the program name */
      progname = *argv++;
--- 114,120 ----
      }
      ifn.CreateJavaVM = 0; ifn.GetDefaultJavaVMInitArgs = 0;
      if (!LoadJavaVM(jvmtype, &ifn))
!         return 1;
  
      /* Grab the program name */
      progname = *argv++;
***************
*** 129,135 ****
      /* Preprocess wrapper arguments */
      TranslateDashJArgs(&argc, &argv);
      if (!AddApplicationOptions())
!       return 1;
  #endif
  
      /* Set default CLASSPATH */
--- 133,139 ----
      /* Preprocess wrapper arguments */
      TranslateDashJArgs(&argc, &argv);
      if (!AddApplicationOptions())
!         return 1;
  #endif
  
      /* Set default CLASSPATH */
***************
*** 145,151 ****
        if (ifn.GetDefaultJavaVMInitArgs(&args) != JNI_OK ||
                args.classpath == 0) {
            fprintf(stderr, "Could not get default system class path.\n");
!           return 1;
        }
        buf = MemAlloc(strlen(args.classpath) + strlen(s) + 2);
        sprintf(buf, "%s%c%s", args.classpath, PATH_SEPARATOR, s);
--- 149,155 ----
        if (ifn.GetDefaultJavaVMInitArgs(&args) != JNI_OK ||
                args.classpath == 0) {
            fprintf(stderr, "Could not get default system class path.\n");
!             return 1;
        }
        buf = MemAlloc(strlen(args.classpath) + strlen(s) + 2);
        sprintf(buf, "%s%c%s", args.classpath, PATH_SEPARATOR, s);
***************
*** 158,164 ****
  
      /* Parse command line options */
      if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret)) {
!       return ret;
      }
  
      /* Override class path if -jar flag was specified */
--- 162,168 ----
  
      /* Parse command line options */
      if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret)) {
!         return ret;
      }
  
      /* Override class path if -jar flag was specified */
***************
*** 172,195 ****
        start = CounterGet();
      if (!InitializeJVM(&vm, &env, &ifn)) {
        fprintf(stderr, "Could not create the Java virtual machine.\n");
!       return 1;
      }
  
      if (printVersion) {
          PrintJavaVersion(env);
        if ((*env)->ExceptionOccurred(env)) {
            (*env)->ExceptionDescribe(env);
!           ret = 1;
        } else {
!           ret = 0;
        }
-       goto leave;
      }
  
      /* If the user specified neither a class name or a JAR file */
      if (jarfile == 0 && classname == 0) {
        PrintUsage();
!       goto leave;
      }
  
      if (debug) {
--- 176,198 ----
        start = CounterGet();
      if (!InitializeJVM(&vm, &env, &ifn)) {
        fprintf(stderr, "Could not create the Java virtual machine.\n");
!         return 1;
      }
  
      if (printVersion) {
          PrintJavaVersion(env);
        if ((*env)->ExceptionOccurred(env)) {
            (*env)->ExceptionDescribe(env);
!             return 1;
        } else {
!             return 0;
        }
      }
  
      /* If the user specified neither a class name or a JAR file */
      if (jarfile == 0 && classname == 0) {
        PrintUsage();
!         return 0;
      }
  
      if (debug) {
***************
*** 198,203 ****
--- 201,225 ----
               (jint)Counter2Micros(end-start));
      }
  
+     *prun = JNI_TRUE;
+     return 0;
+ }
+ 
+ void *
+ run_main(void *pret_arg)
+ {
+     int *pret = (int *)pret_arg;
+     jclass mainClass;
+     jmethodID mainID;
+     jobjectArray mainArgs;
+     JNIEnv *env = 0;
+ 
+     if ((*vm)->AttachCurrentThread(vm, (void **)&env, NULL) != 0) {
+       fprintf(stderr, "Could not attach thread.\n");
+         *pret = 1;
+         return NULL;
+     }
+ 
      /* At this stage, argc/argv have the applications' arguments */
      if (debug) {
        int i = 0;
***************
*** 208,231 ****
        }
      }
  
-     ret = 1;
- 
      /* Get the application's main class */
      if (jarfile != 0) {
        jstring mainClassName = GetMainClassName(env, jarfile);
        if (mainClassName == NULL) {
            fprintf(stderr, "Failed to load Main-Class manifest attribute "
                    "from\n%s\n", jarfile);
!           goto leave;
        }
        if ((*env)->ExceptionOccurred(env)) {
            (*env)->ExceptionDescribe(env);
!           goto leave;
        }
        classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
        if (classname == NULL) {
            (*env)->ExceptionDescribe(env);
!           goto leave;
        }
        mainClass = LoadClass(env, classname);
        (*env)->ReleaseStringUTFChars(env, mainClassName, classname);
--- 230,254 ----
        }
      }
  
      /* Get the application's main class */
      if (jarfile != 0) {
        jstring mainClassName = GetMainClassName(env, jarfile);
        if (mainClassName == NULL) {
            fprintf(stderr, "Failed to load Main-Class manifest attribute "
                    "from\n%s\n", jarfile);
!             *pret = 1;
!             return NULL;
        }
        if ((*env)->ExceptionOccurred(env)) {
            (*env)->ExceptionDescribe(env);
!             *pret = 1;
!             return NULL;
        }
        classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
        if (classname == NULL) {
            (*env)->ExceptionDescribe(env);
!             *pret = 1;
!             return NULL;
        }
        mainClass = LoadClass(env, classname);
        (*env)->ReleaseStringUTFChars(env, mainClassName, classname);
***************
*** 234,240 ****
      }
      if (mainClass == NULL) {
          (*env)->ExceptionDescribe(env);
!       goto leave;
      }
  
      /* Get the application's main method */
--- 257,264 ----
      }
      if (mainClass == NULL) {
          (*env)->ExceptionDescribe(env);
!         *pret = 1;
!         return NULL;
      }
  
      /* Get the application's main method */
***************
*** 246,259 ****
        } else {
            fprintf(stderr, "No main method found in specified class.\n");
        }
!       goto leave;
      }
  
      /* Build argument array */
      mainArgs = NewPlatformStringArray(env, argv, argc);
      if (mainArgs == NULL) {
        (*env)->ExceptionDescribe(env);
!       goto leave;
      }
  
      /* Invoke main method. */
--- 270,285 ----
        } else {
            fprintf(stderr, "No main method found in specified class.\n");
        }
!         *pret = 1;
!         return NULL;
      }
  
      /* Build argument array */
      mainArgs = NewPlatformStringArray(env, argv, argc);
      if (mainArgs == NULL) {
        (*env)->ExceptionDescribe(env);
!         *pret = 1;
!         return NULL;
      }
  
      /* Invoke main method. */
***************
*** 265,271 ****
           stack trace as ExceptionDescribe and could never actually be
           overridden by application programs. */
        (*env)->ExceptionDescribe(env);
!       goto leave;
      }
  
      /*
--- 291,298 ----
           stack trace as ExceptionDescribe and could never actually be
           overridden by application programs. */
        (*env)->ExceptionDescribe(env);
!         *pret = 1;
!         return NULL;
      }
  
      /*
***************
*** 273,286 ****
       * the application's main method exits.
       */
      if ((*vm)->DetachCurrentThread(vm) != 0) {
!       fprintf(stderr, "Could not detach main thread.\n");
!       goto leave;
      }
-     ret = 0;
  
! leave:
      (*vm)->DestroyJavaVM(vm);
!     return ret;
  }
  
  /*
--- 300,349 ----
       * the application's main method exits.
       */
      if ((*vm)->DetachCurrentThread(vm) != 0) {
!       fprintf(stderr, "Could not detach thread.\n");
!         *pret = 1;
!         return NULL;
      }
  
!     *pret = 0;
!     return NULL;
! }
! 
! void
! destroy_vm(void)
! {
      (*vm)->DestroyJavaVM(vm);
! }
! 
! int
! main(int argc_local, char **argv_local)
! {
!     pthread_t tid;
!     int ret;
!     jboolean run;
! 
!     argc = argc_local;
!     argv = argv_local;
! 
!     if ((ret = initialize_vm(&run)) != 0)
!         exit(ret);
! 
!     if (run) {
!         if (createThread) {
!             pthread_create(&tid, NULL, run_main, &ret);
!             pthread_join(tid, NULL);
!         } else {
!             run_main(&ret);
!         }
! 
!         if (ret != 0)
!             exit(ret);
! 
!         destroy_vm();
!     }
!     
!     exit(0);
!     return -1;
  }
  
  /*
***************
*** 358,363 ****
--- 421,428 ----
        } else if (strcmp(arg, "-version") == 0) {
            printVersion = JNI_TRUE;
            return JNI_TRUE;
+       } else if (strcmp(arg, "-createthread") == 0) {
+           createThread = JNI_TRUE;
        } else if (strcmp(arg, "-X") == 0) {
            *pret = PrintXUsage();
            return JNI_FALSE;


----------------------------------------------------------------------
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to