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

PopFrame may fail to detect if the top Java frame cannot be popped

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P3
    • Resolution: Duplicate
    • Affects Version/s: 1.4.0
    • Fix Version/s: None
    • Component/s: vm-legacy
    • Labels:
      None
    • Subcomponent:
    • CPU:
      sparc
    • OS:
      solaris_8

      Description

      I suspect there is a bug in PopFrame that determines if the top Java frame
      can be popped or not. The current top Java frame (which is usually not
      the first frame on the stack since the current thread is suspended) is allowed
      to be popped only if [top-1] frame is also a Java frame (could be interpreted
      or optimized).

      The current implementation of PopFrame uses vframeStream to walk the
      stack but it hides all the internal stubs and individual native frames.
      I believe vframeStream does return JNI native calls.

      My concern is that vframeStream hides some frames between two Java frames
      and thus instead of returning JVMDI_ERROR_NO_MORE_FRAME, PopFrame allows a
      Java frame [top] to be popped but [top-1] frame is not a Java frame since
      vframeStream.next() returns a Java frame (which could be [top - n] frame
      on the stack).

      JVMDI_ERROR_NO_MORE_FRAME is the current error code returned by PopFrame.
      Perhaps we shall have a more meaningful one (e.g. INVALID_POPFRAME).

      I file this bug so that someone can take a closer look at what the expected
      behavior of PopFrame shall be and check if the current implementation
      using vframeStream works as expected or not.

      Please feel free to close it if you find PopFrame working as it expects.

      I am particularly concerned about a stub routine generated for callout to VM
      from Java code.

      I use the stack trace Swamy sent out for PopAsynchronous test failure
      as an example (which he claims it's no longer reproducible):
      > > Testcase calls thread suspend at this point and calls pop frame:
      > >
      > > [13] jvmdi::at_single_stepping_point(
      > > [14] InterpreterRuntime::at_safepoint(
      > > [15] 0xf9c0c778 <== some java code
      > > [16] 0xf9c00528
      > > [17] JavaCalls::call_helper(
      > > [18] os::os_exception_wrapper(
      > > [19] JavaCalls::call(
      > > [21] Exceptions::new_exception(
      > > [22] Exceptions::new_exception(
      > > [23] InterpreterRuntime::create_exception(
      > > [24] 0xf9c0d4d8(
      > > [25] 0xf9c8fc58( <=== fibonacci()

      We shall find out:
      1) what frame #16 and frame #24 are (stub routines or not?)
      2) does vframeStream hide frame #16 and #24 (i.e. which frame
      vframeStream.next() returns when walking the stack)
      3) does PopFrame allow to pop frame #15? Is it supposed to allow?

      Below are some email snipplets from Misha:

      Mandy Chung wrote:
      > With my limited understanding of how PopFrame works, I think this
      > looks like a problem with Java method invoked from a VM call-out
      > that is not currently handled with the current PopFrame
      > implementation.
      >
      > So I include Misha in the email thread and see if he has any
      > insight.
      >
      > When a Java frame is "marked" to be popped (i.e. when PopFrame is
      > called), this Java frame will be popped when the thread is resumed
      > and returning from VM to Java execution. At this transition point,
      > the VM will do the following steps (some details are skipped):
      > 1. empty expression stack and unlock monitors, if any
      > 2. remove this activation
      > 3. preserve args entry
      > 4. dispatch next bytecode...

      .. which bytecode is in fact not the "next", but still the "current" one in the
      [top-1] method. Thus, this bytecode is necessarily a call to the method just popped.

      >
      > Misha, please correct me if my description above is incorrect.

      I believe it's correct.

      >
      > This should work perfectly fine for Java frames that are not the
      > last one in one set of consecutive Java method calls. For example,
      > A calls B and B calls C and no VM callouts are made for these
      > calls. Popping C and B should work. If VM calls A for some runtime
      > support, does the current implementation support to pop A?

      If the [top-1] frame is not a Java frame, PopFrame just shouldn't work (i.e. should
      return some non-zero JVMDI_ERROR_...). In fact, as far as I remember, there is a test
      in the PopFrame code, that checks just this condition - that two topmost frames are
      both Java frames. You may want to verify this (check jvmdi_hotswap.cpp, PopFrame()
      function) - maybe this test is too primitive and accepts some cases that should in
      fact be rejected?

      Misha

      > > >
      > > > This should work perfectly fine for Java frames that are not the
      > > > last one in one set of consecutive Java method calls. For example,
      > > > A calls B and B calls C and no VM callouts are made for these
      > > > calls. Popping C and B should work. If VM calls A for some runtime
      > > > support, does the current implementation support to pop A?
      > >
      > > If the [top-1] frame is not a Java frame, PopFrame just shouldn't work (i.e. should
      > > return some non-zero JVMDI_ERROR_...). In fact, as far as I remember, there is a test
      > > in the PopFrame code, that checks just this condition - that two topmost frames are
      > > both Java frames. You may want to verify this (check jvmdi_hotswap.cpp, PopFrame()
      > > function) - maybe this test is too primitive and accepts some cases that should in
      > > fact be rejected?
      >
      > PopFrame uses vframeStream to walk the stack which I believe it
      > skips irrelevant frames and thus doesn't return error as it
      > suppposes to.

      I believe we should be quite careful about what is "irrelevant". Can we make it really
      clear which frames we should/should not count in the above test? I.e. maybe in the case
      below we really should throw away frames 13 and 14 if 12 is a normal Java frame? After
      all, 13 and 14 seem to be not real native JNI frames (which is a real problem), but rather
      (as far as I can guess from names) frames for special JVM-internal debugger-specific
      functions. Maybe these should be made aware of a popframe event, similar to how currently
      some "jvm call" (forgot the name) function code supports it?

      Misha

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              kbr Kenneth Russell (Inactive)
              Reporter:
              mchung Mandy Chung
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: