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 <nativehelper/JNIHelp.h>
25
26 static JavaVM* javaVm = nullptr;
27
TestThreadNaming(void * arg)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 if (exception_message == nullptr) {
75 exception_message = new std::string("Detach failed");
76 }
77 }
78
79 return exception_message;
80 }
81
Java_libcore_java_lang_ThreadTest_nativeTestNativeThreadNames(JNIEnv * env,jobject)82 extern "C" jstring Java_libcore_java_lang_ThreadTest_nativeTestNativeThreadNames(
83 JNIEnv* env, jobject /* object */) {
84 std::string result;
85
86 // TEST 1: Test that a thread attaching with a specified name (in the
87 // JavaVMAttachArgs) does not have its name changed.
88 pthread_t attacher;
89 if (pthread_create(&attacher, nullptr, TestThreadNaming,
90 reinterpret_cast<void*>(static_cast<uint64_t>(0))) != 0) {
91 jniThrowException(env, "java/lang/IllegalStateException", "Attach failed");
92 }
93
94 std::string* result_test1;
95 if (pthread_join(attacher, reinterpret_cast<void**>(&result_test1)) != 0) {
96 jniThrowException(env, "java/lang/IllegalStateException", "Join failed");
97 }
98
99 if (result_test1 != nullptr) {
100 result.append("test 1: ");
101 result.append(*result_test1);
102 }
103
104 // TEST 2: Test that a thread attaching without a specified name (in the
105 // JavaVMAttachArgs) has its native name changed as per the standard naming
106 // convention.
107 pthread_t attacher2;
108 if (pthread_create(&attacher2, nullptr, TestThreadNaming,
109 reinterpret_cast<void*>(static_cast<uint64_t>(1))) != 0) {
110 jniThrowException(env, "java/lang/IllegalStateException", "Attach failed");
111 }
112
113 std::string* result_test2;
114 if (pthread_join(attacher2, reinterpret_cast<void**>(&result_test2)) != 0) {
115 jniThrowException(env, "java/lang/IllegalStateException", "Join failed");
116 }
117
118 if (result_test2 != nullptr) {
119 result.append("test 2: ");
120 result.append(*result_test2);
121 }
122
123 // Return test results.
124 jstring resultJString = nullptr;
125 if (result.size() > 0) {
126 resultJString = env->NewStringUTF(result.c_str());
127 }
128
129 delete result_test1;
130 delete result_test2;
131
132 return resultJString;
133 }
134
JNI_OnLoad(JavaVM * vm,void *)135 extern "C" int JNI_OnLoad(JavaVM* vm, void*) {
136 javaVm = vm;
137 return JNI_VERSION_1_6;
138 }
139