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

时间:2014-07-22 15:29:29

标签: android c multithreading 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;
    }
}

1 个答案:

答案 0 :(得分:3)

来自pthread_kill手册页:

  

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

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

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

  

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

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

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