8218483: Crash in "assert(_daemon_threads_count->get_value() > daemon_count) failed: thread count mismatch 5 : 5"
authordholmes
Wed, 03 Apr 2019 22:03:39 +0000
changeset 54416 b788c494aa46
parent 54415 00fda51e28cf
child 54417 f87041131515
8218483: Crash in "assert(_daemon_threads_count->get_value() > daemon_count) failed: thread count mismatch 5 : 5" Reviewed-by: dcubed, stuefe
src/hotspot/share/prims/jni.cpp
src/hotspot/share/runtime/thread.cpp
src/hotspot/share/runtime/thread.hpp
test/hotspot/gtest/threadHelper.inline.hpp
--- a/src/hotspot/share/prims/jni.cpp	Wed Apr 03 12:52:37 2019 -0700
+++ b/src/hotspot/share/prims/jni.cpp	Wed Apr 03 22:03:39 2019 +0000
@@ -4166,7 +4166,7 @@
 
   if (attach_failed) {
     // Added missing cleanup
-    thread->cleanup_failed_attach_current_thread();
+    thread->cleanup_failed_attach_current_thread(daemon);
     return JNI_ERR;
   }
 
--- a/src/hotspot/share/runtime/thread.cpp	Wed Apr 03 12:52:37 2019 -0700
+++ b/src/hotspot/share/runtime/thread.cpp	Wed Apr 03 22:03:39 2019 +0000
@@ -2021,6 +2021,10 @@
     _timer_exit_phase1.stop();
     _timer_exit_phase2.start();
   }
+
+  // Capture daemon status before the thread is marked as terminated.
+  bool daemon = is_daemon(threadObj());
+
   // Notify waiters on thread object. This has to be done after exit() is called
   // on the thread (if the thread is the last thread in a daemon ThreadGroup the
   // group should have the destroyed bit set before waiters are notified).
@@ -2089,7 +2093,7 @@
     _timer_exit_phase4.start();
   }
   // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread
-  Threads::remove(this);
+  Threads::remove(this, daemon);
 
   if (log_is_enabled(Debug, os, thread, timer)) {
     _timer_exit_phase4.stop();
@@ -2107,7 +2111,7 @@
   }
 }
 
-void JavaThread::cleanup_failed_attach_current_thread() {
+void JavaThread::cleanup_failed_attach_current_thread(bool is_daemon) {
   if (active_handles() != NULL) {
     JNIHandleBlock* block = active_handles();
     set_active_handles(NULL);
@@ -2129,7 +2133,7 @@
 
   BarrierSet::barrier_set()->on_thread_detach(this);
 
-  Threads::remove(this);
+  Threads::remove(this, is_daemon);
   this->smr_delete();
 }
 
@@ -4455,7 +4459,7 @@
   Events::log(p, "Thread added: " INTPTR_FORMAT, p2i(p));
 }
 
-void Threads::remove(JavaThread* p) {
+void Threads::remove(JavaThread* p, bool is_daemon) {
 
   // Reclaim the ObjectMonitors from the omInUseList and omFreeList of the moribund thread.
   ObjectSynchronizer::omFlush(p);
@@ -4484,11 +4488,8 @@
     }
 
     _number_of_threads--;
-    oop threadObj = p->threadObj();
-    bool daemon = true;
-    if (!is_daemon(threadObj)) {
+    if (!is_daemon) {
       _number_of_non_daemon_threads--;
-      daemon = false;
 
       // Only one thread left, do a notify on the Threads_lock so a thread waiting
       // on destroy_vm will wake up.
@@ -4496,7 +4497,7 @@
         Threads_lock->notify_all();
       }
     }
-    ThreadService::remove_thread(p, daemon);
+    ThreadService::remove_thread(p, is_daemon);
 
     // Make sure that safepoint code disregard this thread. This is needed since
     // the thread might mess around with locks after this point. This can cause it
--- a/src/hotspot/share/runtime/thread.hpp	Wed Apr 03 12:52:37 2019 -0700
+++ b/src/hotspot/share/runtime/thread.hpp	Wed Apr 03 22:03:39 2019 +0000
@@ -1242,7 +1242,7 @@
   };
   void exit(bool destroy_vm, ExitType exit_type = normal_exit);
 
-  void cleanup_failed_attach_current_thread();
+  void cleanup_failed_attach_current_thread(bool is_daemon);
 
   // Testers
   virtual bool is_Java_thread() const            { return true;  }
@@ -2235,7 +2235,7 @@
   // force_daemon is a concession to JNI, where we may need to add a
   // thread to the thread list before allocating its thread object
   static void add(JavaThread* p, bool force_daemon = false);
-  static void remove(JavaThread* p);
+  static void remove(JavaThread* p, bool is_daemon);
   static void non_java_threads_do(ThreadClosure* tc);
   static void java_threads_do(ThreadClosure* tc);
   static void java_threads_and_vm_thread_do(ThreadClosure* tc);
--- a/test/hotspot/gtest/threadHelper.inline.hpp	Wed Apr 03 12:52:37 2019 -0700
+++ b/test/hotspot/gtest/threadHelper.inline.hpp	Wed Apr 03 22:03:39 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -66,7 +66,7 @@
   // Override as JavaThread::post_run() calls JavaThread::exit which
   // expects a valid thread object oop.
   virtual void post_run() {
-    Threads::remove(this);
+    Threads::remove(this, false);
     this->smr_delete();
   }
 
@@ -118,7 +118,7 @@
   // Override as JavaThread::post_run() calls JavaThread::exit which
   // expects a valid thread object oop. And we need to call signal.
   void post_run() {
-    Threads::remove(this);
+    Threads::remove(this, false);
     _post->signal();
     this->smr_delete();
   }