如何在C(Android NDK)中杀死子线程?

在你告诉我我不应该杀死线程然后发送信号/设置一个标志让他们作出反应之前,让我解释一下这个场景:

我正在使用OpenSL API在Android NDK中开发音频播放器(播放本地mp3文件),但Android实现有一个错误,如果我对文件重复执行搜索操作,该线程可悲地挂起一种内部死锁当我尝试释放资源时(SLObjectItf-> Destroy)。

所以我将destroy例程移动到子线程并等待一段固定的时间让它完成,如果没有,我认为该线程被挂起并继续执行泄漏一些资源,这比不得不去系统设置并手动终止应用程序。

我尝试使用信号SIGTERM和SIGKILL来杀死使用pthread_kill的子线程,但它似乎都终止了我的整个应用程序并且Android重新启动它。 我不能使用pthread_cancel,因为线程被绞死,Android NDK也不支持该方法。

有没有办法杀死子线程而不杀死整个应用程序?

编辑:这是线程和启动它的代码

static void *destroyDecoderInBackground(void *ignoredArgument) { if (decoderObject != NULL) { __android_log_print(ANDROID_LOG_INFO, "OpenSLES", "Destroying decoder object"); (*decoderObject)->Destroy(decoderObject); __android_log_print(ANDROID_LOG_INFO, "OpenSLES", "Decoder object destroyed"); decoderObject = NULL; decoderPlay = NULL; decoderSeek = NULL; decoderBufferQueue = NULL; } pthread_mutex_lock(&destroyDecoderLock); pthread_cond_signal(&destroyDecoderCond); pthread_mutex_unlock(&destroyDecoderLock); pthread_exit(0); } static void destroyDecoder(JNIEnv* env) { logJava("Trying to destroy decoder"); struct timespec timeToWait; struct timeval now; // get absolute future time to wait clock_gettime(CLOCK_REALTIME, &timeToWait); timeToWait.tv_nsec = timeToWait.tv_nsec + (500 * 1000000); // wait for destroy decoder thread to complete pthread_mutex_lock(&destroyDecoderLock); pthread_create(&destroyDecoderThread, NULL, &destroyDecoderInBackground, NULL); logJava("Starting waiting"); pthread_cond_timedwait(&destroyDecoderCond, &destroyDecoderLock, &timeToWait); pthread_mutex_unlock(&destroyDecoderLock); logJava("Finished waiting"); if(decoderObject != NULL) { logJava("Destroy decoder hanged, killing thread, resources will leak!!!"); pthread_kill(destroyDecoderThread, SIGTERM); decoderObject = NULL; decoderPlay = NULL; decoderSeek = NULL; decoderBufferQueue = NULL; } } 

pthread_kill手册页:

信号处理在整个过程中:如果安装了信号处理程序,将在线程线程中调用处理程序,但如果信号的处置是“停止”,“继续”或“终止”,则此操作将影响整个过程。

在Dalvik中,用于特殊处理的信号(例如SIGQUIT转储堆栈, SIGUSR1导致GC)在创建任何线程之前被阻塞,然后使用sigwait()在SignalCatcher线程中解除阻塞。 您无法更改您无法控制的线程的阻止状态,因此这对您不起作用。

你可以做的是为一个未使用的信号安装一个信号处理程序(例如我不认为运输版本的Dalvik使用SIGUSR2 ),并让它调用pthread_exit() 。 如该函数的手册页中所述:

当线程终止时,不释放进程共享资源(例如,互斥锁,条件变量,信号量和文件描述符),并且不调用使用atexit(3)注册的函数。

这听起来像是“理想的”行为。

说了这么多,请不要放弃不这样做的希望。 :-)听起来你认识到问题的一部分(资源泄漏),但你还必须考虑不一致状态的可能性,例如认为它们被退出的线程所持有的互斥体。 您可以最终处于其他线程将挂起或行为奇怪的状态。