# HG changeset patch # User dholmes # Date 1554329019 0 # Node ID b788c494aa4659ee72786e2f4a9ae98a14385c31 # Parent 00fda51e28cffabe3f0ed50d131be85680eb031c 8218483: Crash in "assert(_daemon_threads_count->get_value() > daemon_count) failed: thread count mismatch 5 : 5" Reviewed-by: dcubed, stuefe diff -r 00fda51e28cf -r b788c494aa46 src/hotspot/share/prims/jni.cpp --- 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; } diff -r 00fda51e28cf -r b788c494aa46 src/hotspot/share/runtime/thread.cpp --- 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 diff -r 00fda51e28cf -r b788c494aa46 src/hotspot/share/runtime/thread.hpp --- 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); diff -r 00fda51e28cf -r b788c494aa46 test/hotspot/gtest/threadHelper.inline.hpp --- 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(); }