1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <memory> 18 #include <string> 19 20 #include <pthread.h> 21 #include <sys/prctl.h> 22 23 #include <jni.h> 24 #include "JNIHelp.h" 25 26 static JavaVM* javaVm = nullptr; 27 28 static void* TestThreadNaming(void* arg) { 29 const bool attach_with_name = (reinterpret_cast<uint64_t>(arg) == 1); 30 const std::string native_thread_name = "foozball"; 31 pthread_setname_np(pthread_self(), native_thread_name.c_str()); 32 33 JNIEnv* env; 34 JavaVMAttachArgs args; 35 args.version = JNI_VERSION_1_6; 36 args.group = nullptr; 37 if (attach_with_name) { 38 args.name = native_thread_name.c_str(); 39 } else { 40 args.name = nullptr; 41 } 42 43 if (javaVm->AttachCurrentThread(&env, &args) != JNI_OK) { 44 return new std::string("Attach failed"); 45 } 46 47 std::string* exception_message = nullptr; 48 std::unique_ptr<char[]> thread_name(new char[32]); 49 if (prctl(PR_GET_NAME, reinterpret_cast<unsigned long>(thread_name.get()), 0L, 0L, 0L) == 0) { 50 // If a thread is attached with a name, the native thread name must be set to 51 // the supplied name. In this test, the name we attach with == the 52 // native_thread_name. 53 if (attach_with_name && (thread_name.get() != native_thread_name)) { 54 exception_message = new std::string("expected_thread_name != thread_name: "); 55 exception_message->append("expected :"); 56 exception_message->append(native_thread_name); 57 exception_message->append(" was :"); 58 exception_message->append(thread_name.get()); 59 } 60 61 // On the other hand, if the thread isn't attached with a name - the 62 // runtime assigns a name according to the usual thread naming scheme. 63 if (!attach_with_name && strncmp(thread_name.get(), "Thread", 6)) { 64 exception_message = new std::string("unexpected thread name : "); 65 exception_message->append(thread_name.get()); 66 } 67 } else { 68 exception_message = new std::string("prctl(PR_GET_NAME) failed :"); 69 exception_message->append(strerror(errno)); 70 } 71 72 73 if (javaVm->DetachCurrentThread() != JNI_OK) { 74 exception_message = new std::string("Detach failed"); 75 } 76 77 return exception_message; 78 } 79 80 extern "C" jstring Java_libcore_java_lang_ThreadTest_nativeTestNativeThreadNames( 81 JNIEnv* env, jobject /* object */) { 82 std::string result; 83 84 // TEST 1: Test that a thread attaching with a specified name (in the 85 // JavaVMAttachArgs) does not have its name changed. 86 pthread_t attacher; 87 if (pthread_create(&attacher, nullptr, TestThreadNaming, 88 reinterpret_cast<void*>(static_cast<uint64_t>(0))) != 0) { 89 jniThrowException(env, "java/lang/IllegalStateException", "Attach failed"); 90 } 91 92 std::string* result_test1; 93 if (pthread_join(attacher, reinterpret_cast<void**>(&result_test1)) != 0) { 94 jniThrowException(env, "java/lang/IllegalStateException", "Join failed"); 95 } 96 97 if (result_test1 != nullptr) { 98 result.append("test 1: "); 99 result.append(*result_test1); 100 } 101 102 // TEST 2: Test that a thread attaching without a specified name (in the 103 // JavaVMAttachArgs) has its native name changed as per the standard naming 104 // convention. 105 pthread_t attacher2; 106 if (pthread_create(&attacher2, nullptr, TestThreadNaming, 107 reinterpret_cast<void*>(static_cast<uint64_t>(1))) != 0) { 108 jniThrowException(env, "java/lang/IllegalStateException", "Attach failed"); 109 } 110 111 std::string* result_test2; 112 if (pthread_join(attacher2, reinterpret_cast<void**>(&result_test2)) != 0) { 113 jniThrowException(env, "java/lang/IllegalStateException", "Join failed"); 114 } 115 116 if (result_test2 != nullptr) { 117 result.append("test 2: "); 118 result.append(*result_test2); 119 } 120 121 // Return test results. 122 jstring resultJString = nullptr; 123 if (result.size() > 0) { 124 resultJString = env->NewStringUTF(result.c_str()); 125 } 126 127 delete result_test1; 128 delete result_test2; 129 130 return resultJString; 131 } 132 133 extern "C" int JNI_OnLoad(JavaVM* vm, void*) { 134 javaVm = vm; 135 return JNI_VERSION_1_6; 136 } 137