JDK-6880972 : examine JVM/TI uses of Threads::number_of_threads() == 0 & SafepointSynchronize::is_at_safepoint()
  • Type: Bug
  • Component: hotspot
  • Sub-Component: jvmti
  • Affected Version: hs17
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: generic
  • CPU: generic
  • Submitted: 2009-09-10
  • Updated: 2023-12-13
  • Resolved: 2016-11-30
Related Reports
Relates :  
Relates :  
Description
This issue came up during the code review of the fix for:

    6419370 4/4 new jmethodID code has tiny holes in synchronization

since the comments were about existing code, I filed this new bug.

JVM/TI's uses of Threads::number_of_threads() need to be closely
examined and verified to be valid. Consider this use:

src/share/vm/prims/jvmtiEnv.cpp:

  2933  // rmonitor - pre-checked for validity
  2934  jvmtiError
  2935  JvmtiEnv::RawMonitorEnter(JvmtiRawMonitor * rmonitor) {
  2936    if (Threads::number_of_threads() == 0) {
  2937      // No JavaThreads exist so ObjectMonitor enter cannot be
  2938      // used, add this raw monitor to the pending list.
  2939      // The pending monitors will be actually entered when
  2940      // the VM is setup.
  2941      // See transition_pending_raw_monitors in create_vm()
  2942      // in thread.cpp.
  2943      JvmtiPendingMonitors::enter(rmonitor);
  2944    } else {
  2945      int r;
  2946      Thread* thread = Thread::current();

RawMonitors are built on top of ObjectMonitors and thus cannot be
used before we have JavaThreads so the above use is generally
correct. The only part I wonder about is proper coordination
between agent thread(s) adding to JvmtiPendingMonitors and the
create Java VM thread cleaning up JvmtiPendingMonitors after
the main JavaThread has been started. More investigation is
needed there.


Now consider this usage:

src/share/vm/prims/jvmtiEnv.cpp

   293  // prefix_count - pre-checked to be greater than or equal to 0
   294  // prefixes - pre-checked for NULL
   295  jvmtiError
   296  JvmtiEnv::SetNativeMethodPrefixes(jint prefix_count, char** prefixes) {
   297    // Have to grab JVMTI thread state lock to be sure that some thread
   298    // isn't accessing the prefixes at the same time we are setting them.
   299    // No locks during VM bring-up.
   300    if (Threads::number_of_threads() == 0) {
   301      return set_native_method_prefixes(prefix_count, prefixes);
   302    } else {
   303      MutexLocker mu(JvmtiThreadState_lock);
   304      return set_native_method_prefixes(prefix_count, prefixes);
   305    }
   306  } /* end SetNativeMethodPrefixes */

The comment on line 299 explains why we don't grab the
JvmtiThreadState_lock, but I'm not sure that it is right.
Consider src/share/vm/runtime/mutexLocker.hpp:

extern Mutex*   JvmtiThreadState_lock;           // a lock on modification of JVMTI thread data

A Mutex object is different than a JvmtiRawMonitor/ObjectMonitor
object so I think we need to figure out if there is a real reason
for not grabbing various Mutex objects in JVM/TI.


And finally consider this usage:

src/share/vm/prims/jvmtiExport.cpp:

   438  char**
   439  JvmtiExport::get_all_native_method_prefixes(int* count_ptr) {
   440    // Have to grab JVMTI thread state lock to be sure environment doesn't   441    // go away while we iterate them.  No locks during VM bring-up.
   442    if (Threads::number_of_threads() == 0 || SafepointSynchronize::is_at_safepoint()) {
   443      return JvmtiEnvBase::get_all_native_method_prefixes(count_ptr);
   444    } else {
   445      MutexLocker mu(JvmtiThreadState_lock);
   446      return JvmtiEnvBase::get_all_native_method_prefixes(count_ptr);
   447    }
   448  }

The "Threads::number_of_threads() == 0" check has the same concerns
as mentioned before. The SafepointSynchronize::is_at_safepoint()
check allows the VMThread to call the function without trying to
acquire the Mutex. However, because that check does not also verify
that the caller is the VMThread there is concern that another thread
could be permitted unlocked access. If there are other threads that
could be using this unlocked code path during a safepoint, then there
is also concern that the system could leave the safepoint so we'd
have unlocked access racing with locked access. More investigation
is needed here also.

Comments
This is not on our list of current priorities. If this changes, please reopen this issue.
30-11-2016

PUBLIC COMMENTS > The SafepointSynchronize::is_at_safepoint() check allows the VMThread to call > the function without trying to acquire the Mutex. However, because that check > does not also verify that the caller is the VMThread there is concern that > another thread could be permitted unlocked access. If the VM is at a safepoint then no thread should be able to execute this code other than the VMThread.
12-07-2011