2017-02-06 15 views
1

Прежде всего, у меня нет предшествующих знаний C. Я пытаюсь собрать нить. Вот мой пример. Я призываю начать сначала, затем после выполнения некоторой работы на стороне Java я называю остановитьNDK C++ std :: thread abort crash on join

#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; 
    } 

    } 

Над обычно работает нормально, но пока я не могу воспроизвести это мой сам, я получаю Native аварии журналов о несостоявшемся потоке только после вызова

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

, например

#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) 

Как я могу предотвратить эту катастрофу? Я попытался добавить блокировку и разблокировку мьютекса, чтобы функционировать и остановиться, как показано ниже, но это заставляет цикл зависать некоторое время, прежде чем он завершится, что неприемлемо в этом случае.

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

Я снял замки, вместо этого, я отделяя нить с Detach() в JNI старте (..) только после его создания и позволяя ему работать. Затем подождите 200 мс при остановке JNI (...) после установки do_job = true

Будет ли это работать?

+0

Пожалуйста, исправьте отступ кода в вашем примере. –

ответ

1

_ZNSt6threadaSEOS_ является std::thread::operator=(std::thread&&). Вы можете использовать утилиту c++filt для демонстрации имен символов.

Из документации станд :: Thread :: оператор =

Если * это по-прежнему имеет связанный выполняемый поток (== т.е. присоединяемые() истина), вызовите станд :: прекратить(). В противном случае присваивается состояние другого значения * и устанавливает другое состояние по умолчанию.

Значит, ваша глобальная переменная LOOPING_THREAD содержит активную тему, которая еще не закончена.

+0

Спасибо. Таким образом, превратив его в локальную переменную и вызвав detach() после ее создания, исправить? Вложение его как std :: thread LOOPING_THREAD = std :: thread (looping, 1); LOOPING_THREAD.detach(); – nLL

+0

Если вы вызываете 'detach', вы не сможете присоединиться к нити. У вас также есть возможность правильно завершить поток при завершении процесса. И отключение потока не решит никаких проблем с владением данными, которые использует поток. Таким образом, отсоединение потока решит эту конкретную проблему, но, скорее всего, вы столкнетесь со многими другими проблемами, если пойдете так. Лучше уточнить отношения с владельцем в программе и <в зависимости от ваших потребностей, а не разрешать одновременное выполнение нескольких потоков. –

+0

Функция, вызываемая в этом потоке, представляет собой очень простой цикл while, который выходит после n раз подряд или если выполняется условие. Я понимаю, что когда цикл существует, поток тоже выйдет, поэтому нет необходимости присоединяться? Верный? – nLL

 Смежные вопросы

  • Нет связанных вопросов^_^