nLL
nLL

Reputation: 5672

NDK c++ std::thread abort crash on join

First of all, I have no prior C knowledge. I am trying to put together a thread. Here is my example. I call start first, then after doing some work on java side I call stop

#include <jni.h>
#include <thread>
std::thread LOOPING_THREAD;
bool do_job = false;

//looping func
 void looping(int test) {
   while (do_job) {
    LOGD("Doing job");
   }
}

//start
JNIEXPORT jint JNICALL
Java_com_example_start(JNIEnv *env, jobject thiz,) {
LOOPING_THREAD = std::thread(looping, 1);
}

JNIEXPORT jint JNICALL
Java_com_example_stop(JNIEnv *env, jobject thiz) {
do_job= false;
LOOPING_THREAD.join();
return 0;
  }

  }

Above usually works fine but while I cannot reproduce it my self, I get Native crash logs about aborted thread just after calling

LOOPING_THREAD = std::thread(looping, 1);

for example

#00 pc 00044340  /system/lib/libc.so (tgkill+12)
#01 pc 00041f41  /system/lib/libc.so (pthread_kill+32)
#02 pc 0001ba6f  /system/lib/libc.so (raise+10)
#03 pc 00018c11  /system/lib/libc.so (__libc_android_abort+34)
#04 pc 000167d0  /system/lib/libc.so (abort+4)
#05 pc 00010aa3  /data/app/com.app-1/lib/arm/libapp.so    (_ZN9__gnu_cxx27__verbose_terminate_handlerEv+230)
#06 pc 0000cfb9  /data/app/com.app-1/lib/arm/libapp.so (_ZN10__cxxabiv111__terminateEPFvvE+4)
#07 pc 0000d0c1  /data/app/com.app-1/lib/arm/libapp.so (_ZSt9terminatev+8)
#08 pc 00008ddb  /data/app/com.app-1/lib/arm/libapp.so (_ZNSt6threadaSEOS_+38)

How can I prevent this crash? I tried to add mutex lock and unlock to function and stop as below but it causes loop to hang for a while before it completes, which is not acceptable in this case.

 void looping(int test) {
    while (do_job) {
      mutex.lock()
     LOGD("Doing job");
     mutex.unlock()
  }

 JNIEXPORT jint JNICALL
  Java_com_example_stop(JNIEnv *env, jobject thiz) {
   mutex.lock()
   do_job= false;
   mutex.unlock()
   return 0;
 }

Update

I have removed locks, instead, I am detaching the thread with detach() at JNI start(..) just after creating it and letting it run. Then, wait 200 ms at JNI stop(...) after setting do_job = true

Would that work?

Upvotes: 1

Views: 2142

Answers (1)

Alexey Guseynov
Alexey Guseynov

Reputation: 5304

_ZNSt6threadaSEOS_ is a std::thread::operator=(std::thread&&). You can use c++filt utility to demangle symbol names.

From documentation of std::thread::operator=

If *this still has an associated running thread (i.e. joinable() == true), call std::terminate(). Otherwise, assigns the state of other to *this and sets other to a default constructed state.

So your global variable LOOPING_THREAD contains active thread which has not finished yet.

Upvotes: 1

Related Questions