Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4108464

green VM exits with one non-daemon thread running (other than main thread)

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P1
    • Resolution: Duplicate
    • Affects Version/s: 1.2.0
    • Fix Version/s: None
    • Component/s: hotspot
    • Subcomponent:
    • CPU:
      sparc
    • OS:
      solaris_2.5

      Description

      With the JDK1.2Beta3-E build's green threads VM, running the following simple
      class exits immediately. It should just hang, because its main method creates
      a non-daemon thread which waits forever. As far as I can tell, the bug is that
      if main thread falls off the edge, the VM will exit unless there is *more* than
      one other non-daemon ("user") thread running.

      class ShouldNotExit extends Thread {
       
          public void run() {
              while (true) {
                  try {
                      Thread.sleep(Long.MAX_VALUE);
                  } catch (InterruptedException e) {
                      // ignore interrupts
                  }
              }
          }
       
          public static void main(String[] args) {
              Thread t = new ShouldNotExit();
              t.start();
          }
      }

      The following function "WaitRoDie()" in src/solaris/hpi/green_thread/src/
      threads_md.c is called after the main method finishes and the main thread falls
      off the edge, to wait for all of the user threads to finish. It waits for
      the global "UserThreadCount" to drop to 1; the surrounding comments seem to
      imply that it still counts the main thread as one user thread; hence, it
      attempts to wait for no user threads *other* than the main thread. However,
      the cause of the bug seems to be that at the point where WaitToDie() is
      called, the main thread is no longer being counted in UserThreadCount.

      The added debugging output shown demonstrates that when this function is
      called, the application's non-daemon thread has been created, and
      UserThreadCount is 1 (so the VM will then exit, incorrectly).

      /*
       * The primordial thread is not allowed to fall off the end of start_java()
       * until the Java system is about to exit. This is allowed only when the
       * primordial thread is the sole "user" thread remaining.
       */
      void
      WaitToDie() {
          QUEUE_LOCK(sysThreadSelf());
      /*****/
          DumpThreads();
          jio_fprintf(stderr,
                      "WaitToDie(): UserThreadCount = %d\n", UserThreadCount);
      /*****/
          while (UserThreadCount > 1) { /* Primordial thread considered user */
              QUEUE_WAIT(sysThreadSelf());
          }
          QUEUE_UNLOCK(sysThreadSelf());
      }

      The native threads version of this function has the identical logic (it assumes
      that the main thread is still counted in UserThreadCount at this point) and it
      seems to work fine.

      The following is an excerpt from running dbx on the VM executing this class.
      Breakpoints are set at every line where the global "UserThreadCount" is
      modified. It is first incremented to 1 for the main thread in
      sysThreadBootstrap(), then it is incremented to 2 in sysThreadCreate when the
      application's "ShouldNotExit" thread is created. It is then decremented down
      to 1 in removeFromActiveQ when java_main calls DetachCurrentThread. Finally,
      when java_main calls DestroyJavaVM, WaitToDie() gets called to wait for all of
      the other user threads to finish, but since UserThreadCount remains at 1, it
      exits immediately.

      I'm not sure how this is *supposed* to be working, but somehow the main thread
      should still be counted in UserThreadCount at this point... perhaps either it
      shouldn't have been decremented through the DetachCurrentThread call, or it
      should have been incremented again when java_main called AttachCurrentThread
      (??)

      To reiterate, this bug was introduced into the JDK1.2Beta3-E promoted build;
      the test succeeds in JDK1.2Beta3-D, so the problem should be found in the
      deltas since the integration for JDK1.2Beta3-D.

      (dbx) stop at threads_md.c:138
      (2) stop at "threads_md.c":138
      (dbx) stop at threads_md.c:324
      (3) stop at "threads_md.c":324
      (dbx) stap at threads_md.c:867
      stap: not found
      (dbx) stop at threads_md.c:867
      (4) stop at "threads_md.c":867
      (dbx) ignore POLL
      (dbx) run ShouldNotExit
      Running: java_g ShouldNotExit
      (process id 16921)
      stopped in sysThreadBootstrap at line 138 in file "threads_md.c"
        138 UserThreadCount++; /* The main thread considered user */
      (dbx) where
      =>[1] sysThreadBootstrap(tid = 0x20a98), line 138 in "threads_md.c"
        [2] InitializeJavaVM(ee = 0x20a20, args = 0xeffff714), line 454 in "javai.c"
        [3] JNI_CreateJavaVM(vm = 0xef677ed4, penv = 0xef677ed8, args = 0xeffff714), l
      ine 3427 in "jni.c"
        [4] parseOptions(argc = 0, argv = 0xeffff888), line 423 in "java_main.c"
        [5] java_main(argc = 2, argv = 0xeffff884), line 441 in "java_main.c"
        [6] main(argc = 2, argv = 0xeffff884, envp = 0xeffff890), line 25 in "java.c"
      (dbx) cont
      stopped in sysThreadCreate at line 324 in file "threads_md.c"
        324 UserThreadCount++;
      (dbx) where
      =>[1] sysThreadCreate(stack_size = 131072, flags = 1U, start = 0xef73a958 = &Thr
      eadRT0(), tid = 0x77d88), line 324 in "threads_md.c"
        [2] threadCreate(tid = 0xee3046a8, flags = 1U, stack_size = 131072U, func = 0x
      ef73a958 = &ThreadRT0()), line 98 in "threads.c"
        [3] JVM_StartThread(env = 0x20a20, this = 0x25774), line 2259 in "jvm.c"
        [4] sysInvokeNative(0x20a20, 0xef73ab10, 0x25774, 0x2b769, 0x1, 0x0), at 0xef7
      7b764
        [5] invokeJNISynchronizedNativeMethod(o = 0xee3046a8, mb = 0x2a774, args_size
      = 1, ee = 0x20a20), line 443 in "classruntime.c"
        [6] ExecuteJava_C(initial_pc = 0xeffff666 "\xd9", ee = 0x20a20), line 1458 in
      "executeJava.c"
        [7] jni_Invoke(env = 0x20a20, self = 0x2573c, methodID = 0x77b2c, pushArgument
      s = 0xef7194d0 = &`libjvm_g.so`jni.c`jni_PushArgumentsVararg(JNIEnv *env, char *
      terse_signature, JavaFrame *current_frame, void *a), args = 0xeffff724, invokeKi
      nd = 2, reqType = '\n'), line 860 in "jni.c"
        [8] jni_CallStaticVoidMethod(env = 0x20a20, clazz = 0x2573c, methodID = 0x77b2
      c, ...), line 2012 in "jni.c"
        [9] java_main(argc = 2, argv = 0xeffff884), line 473 in "java_main.c"
        [10] main(argc = 2, argv = 0xeffff884, envp = 0xeffff890), line 25 in "java.c"
      (dbx) cont
      stopped in removeFromActiveQ at line 867 in file "threads_md.c"
        867 UserThreadCount--;
      (dbx) where
      =>[1] removeFromActiveQ(t = 0x20a98), line 867 in "threads_md.c"
        [2] sysThreadFree(tid = 0x20a98), line 379 in "threads_md.c"
        [3] threadFree(), line 163 in "threads.c"
        [4] jni_DetachCurrentThread(vm = 0xef79ea8c), line 3637 in "jni.c"
        [5] java_main(argc = 2, argv = 0xeffff884), line 510 in "java_main.c"
        [6] main(argc = 2, argv = 0xeffff884, envp = 0xeffff890), line 25 in "java.c"
      (dbx) cont

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              never Tom Rodriguez
              Reporter:
              peterjones Peter Jones
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: