Thread::current() and JNI pthread interaction

Gerard Ziemski gerard.ziemski at oracle.com
Wed Feb 5 15:04:33 PST 2014


hi Andreas,

I just tested the issue and it's present on Mac as well - I updated your 
bug and also linked related NetBeans on Ubuntu64 bit crash.

I have tested your fix on Mac and it seems fine to me (not an official 
reviewer), though using a pthread_key destructor to reset that same 
pthread_key value back seems a little bit counter-intuitive, so that 
pthread_key destructor could probably benefit from a nice comment. I'm 
unclear on one thing: in the end, do we end up leaking the pthread_key 
and if so is that a big deal or not?

I believe the final fix will need to applied to Mac platform as well as 
Linux.


cheers

On 2/5/2014 10:38 AM, Andreas Eriksson wrote:
> Thanks for looking at this.
>
> I filed a bug at https://bugs.openjdk.java.net/browse/JDK-8033696.
> A correction to my original mail is that it is not Thread::~Thread 
> that resets the thread pointer in the TLS, it is pthreads itself.
>
> I did find a way to change the JVM to workaround this problem:
> By creating a destructor for the thread pointer TLS we can restore the 
> value after pthread has set it to NULL.
> Then when the native code destructor is run the thread pointer is 
> still intact.
>
> Restoring a value in a pthread TLS is explicitly supported according 
> to the man page for pthread_key_create, and it will call the 
> destructor for the restored value again.
> One would have to keep some extra state to make sure the destructor is 
> only called twice, since a pthread implementation is allowed to call 
> the destructor infinite times as long as the value is restored.
>
> On my system pthread calls the destructor a maximum of four times, so 
> the attached JVM patch was sufficient as a proof of concept.
>
> Regards,
> Andreas
>
> On 2014-02-05 17:15, David Simms wrote:
>>
>> This looks like a bug unfortunately, the JNI documentation doesn't 
>> appear to warn against this kind of use.
>>
>> The code in question:
>> 	static void make_key()
>> 	{
>> 		pthread_key_create(&key, detachThread);
>> 	}
>>
>> 	
>> 	/**
>> 	 *  pthread key destructor (runs after the JVM current thread key is already destroyed)
>> 	 */
>> 	static void detachThread(void *p)
>> 	{
>> 		if (p != 0)
>> 		{
>> 			JavaVM *jvm = 0;
>> 			JNIEnv *env = (JNIEnv *) p;
>> 			env->GetJavaVM(&jvm);
>> 			*jint result = jvm->DetachCurrentThread();*
>>
>> The JVM current thread is already toast as you suggest.
>>
>> I believe Andreas that you might already have a simple pain free 
>> work-around from the JVM. Given that the problem only appears on 
>> certain platforms, there may be other case where people migrate to 64 
>> bit and find this nasty crash. Be worth filing a bug...
>>
>> Cheers
>> /David Simms
>>
>>
>> On 02/05/2014 12:47 PM, Andreas Eriksson wrote:
>>> Hi,
>>>
>>> I'm investigating a bug where JNI code (attached, compilation 
>>> instructions below) is using pthread_key_create with a destructor to 
>>> detach the thread from the JVM when the thread is exiting.
>>> This solution works well when running on Solaris or a 32 bit JVM on 
>>> Linux, but when run on 64 bit JVM on Linux the threads hang when 
>>> detaching.
>>>
>>> It turns out that for 64 bit Linux the JVM is also using the 
>>> pthread_key_create, to store the Thread::current() value in a thread 
>>> local storage.
>>> Ssince the thread local storages are reset in Thread::~Thread 
>>> (ThreadLocalStorage::set_thread(NULL)), before the JNI destructor 
>>> runs, we run detachCurrentThread on a thread that has NULL as 
>>> current thread.
>>> With a product build this breaks locks/monitors, and the threads 
>>> hang. With a debug build an assert in Thread::current() is hit instead.
>>>
>>> Everything works if detachCurrentThread is called from the main 
>>> logic instead.
>>>
>>> Is this considered a bug, or maybe this behavior is expected?
>>>
>>> Regards,
>>> Andreas
>>>
>>> Compile native:
>>> # 64bit
>>> JAVA_HOME=/java/linux-x64/jdk1.7.0_45
>>> gcc -shared -fpic  -o libNative.so  -I$JAVA_HOME/include 
>>> -I$JAVA_HOME/include/linux -lstdc++ Callback_Native.cpp
>>>
>>> # 32bit
>>> JAVA_HOME=/java/linux-i586/jdk1.7.0_45
>>> gcc -v -m32 -shared -fpic  -o libNative.so -I$JAVA_HOME/include 
>>> -I$JAVA_HOME/include/linux -lstdc++ Callback_Native.cpp
>>>
>>> Compile java (from callback/src/main/java):
>>> JAVA_HOME=/java/linux-x64/jdk-1.7.0_45
>>> $JAVA_HOME/bin/javac com/test/callback/CallbackTest.java
>>> $JAVA_HOME/bin/javac com/test/callback/App.java
>>>
>>> To run: (from callback/src/main/java)
>>> NATIVE=../../../native
>>> $JAVA_HOME/bin/java -Djava.library.path=$NATIVE com.test.callback.App
>>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/hotspot-runtime-dev/attachments/20140205/7e343b39/attachment-0001.html 


More information about the hotspot-runtime-dev mailing list