Home | History | Annotate | Download | only in native
      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 
     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