From fbb7bd87812505a529e2899a953777fe5a7b092e Mon Sep 17 00:00:00 2001 From: Andreas Eriksson Date: Wed, 2 Apr 2014 18:40:52 +0200 Subject: [PATCH] 8033696: "assert(thread != NULL) failed: just checking" due to Thread::current() and JNI pthread interaction Reviewed-by: dholmes, dsamersoff --- hotspot/src/os/bsd/vm/os_bsd.cpp | 13 ++++++++++++- hotspot/src/os/linux/vm/os_linux.cpp | 13 ++++++++++++- hotspot/src/share/vm/runtime/vmThread.cpp | 3 +++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index 2a71edf0028..686cb06157d 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -917,9 +917,20 @@ void os::free_thread(OSThread* osthread) { ////////////////////////////////////////////////////////////////////////////// // thread local storage +// Restore the thread pointer if the destructor is called. This is in case +// someone from JNI code sets up a destructor with pthread_key_create to run +// detachCurrentThread on thread death. Unless we restore the thread pointer we +// will hang or crash. When detachCurrentThread is called the key will be set +// to null and we will not be called again. If detachCurrentThread is never +// called we could loop forever depending on the pthread implementation. +static void restore_thread_pointer(void* p) { + Thread* thread = (Thread*) p; + os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); +} + int os::allocate_thread_local_storage() { pthread_key_t key; - int rslt = pthread_key_create(&key, NULL); + int rslt = pthread_key_create(&key, restore_thread_pointer); assert(rslt == 0, "cannot allocate thread local storage"); return (int)key; } diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index e9192178ff8..50ae1e453b9 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -1032,9 +1032,20 @@ void os::free_thread(OSThread* osthread) { ////////////////////////////////////////////////////////////////////////////// // thread local storage +// Restore the thread pointer if the destructor is called. This is in case +// someone from JNI code sets up a destructor with pthread_key_create to run +// detachCurrentThread on thread death. Unless we restore the thread pointer we +// will hang or crash. When detachCurrentThread is called the key will be set +// to null and we will not be called again. If detachCurrentThread is never +// called we could loop forever depending on the pthread implementation. +static void restore_thread_pointer(void* p) { + Thread* thread = (Thread*) p; + os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); +} + int os::allocate_thread_local_storage() { pthread_key_t key; - int rslt = pthread_key_create(&key, NULL); + int rslt = pthread_key_create(&key, restore_thread_pointer); assert(rslt == 0, "cannot allocate thread local storage"); return (int)key; } diff --git a/hotspot/src/share/vm/runtime/vmThread.cpp b/hotspot/src/share/vm/runtime/vmThread.cpp index 09ad0a246dc..e974578a838 100644 --- a/hotspot/src/share/vm/runtime/vmThread.cpp +++ b/hotspot/src/share/vm/runtime/vmThread.cpp @@ -305,6 +305,9 @@ void VMThread::run() { _terminate_lock->notify(); } + // Thread destructor usually does this. + ThreadLocalStorage::set_thread(NULL); + // Deletion must be done synchronously by the JNI DestroyJavaVM thread // so that the VMThread deletion completes before the main thread frees // up the CodeHeap.