在你告诉我我不应该杀死线程然后发送信号/设置一个标志让他们做出反应之前,让我解释一下这个场景:
我正在使用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;
}
}
答案 0 :(得分:3)
来自pthread_kill
手册页:
信号处理是整个过程:如果信号处理程序是 安装后,处理程序将在线程线程中调用,但是如果 信号的处理是“停止”,“继续”或“终止”, 这个动作会影响整个过程。
在Dalvik中,用于特殊处理的信号(例如SIGQUIT
转储堆栈,SIGUSR1
导致GC)在创建任何线程之前被阻塞,然后在SignalCatcher线程中解除阻塞使用sigwait()
。您无法更改您无法控制的线程的阻止状态,因此这对您无效。
您可以做的是为未使用的信号安装信号处理程序(例如,我不认为发送版本的Dalvik会使用SIGUSR2
),并让它调用pthread_exit()
。正如该函数的手册页中所述:
当线程终止时,进程共享资源(例如,互斥, 条件变量,信号量和文件描述符)不是 已释放,并且不会调用使用atexit(3)注册的函数。
这听起来像是“理想的”行为。
说了这么多,请不要放弃不这样做的希望。 :-)听起来你觉得问题的一部分(资源泄漏),但你还必须考虑不一致状态的可能性,例如:认为它们被退出的线程所持有的互斥体。您最终可能处于其他线程将挂起或行为奇怪的状态。