如何在C(Android NDK)中杀死子线程? [英] How to kill a child thread in C (Android NDK)?

查看:189
本文介绍了如何在C(Android NDK)中杀死子线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在您告诉我不应该杀死线程而发送信号/设置标志以使它们做出反应之前,让我解释一下这种情况:

Before you tell me that I should not kill threads and instead send a signal/set a flag for them to react, let me explain the scenario:

我正在使用OpenSL API在Android NDK中开发音频播放器(播放本地mp3文件),但是Android实现存在一个错误,即如果我对文件重复执行一次搜索操作,则该线程会不幸地以某种方式挂起尝试释放资源时内部死锁的状态(SLObjectItf-> Destroy).

I'm developing an audio player in Android NDK with OpenSL API (play a local mp3 file), but the Android implementation has a bug where If I perform repeatedly a seek operation on the file, the thread sadly hangs in a kind of internal deadlock when I try to free resources (SLObjectItf->Destroy).

因此,我将销毁例程移至子线程,并等待固定的时间以完成它,如果没有完成,我认为该线程已被挂起并继续执行,从而泄漏了一些资源,这比具有进入系统设置并手动终止该应用程序.

So I moved the destroy routine to a child thread and wait for a fixed amount of time for it to finish, if it doesn't, I consider the thread as hanged and continue execution leaking some resources, which is preferable than having to go to the system settings and manually kill the app.

我试图使用信号SIGTERM和SIGKILL用pthread_kill杀死子线程,但似乎两者都终止了我的整个应用程序,Android重新启动了它.我不能使用pthread_cancel,因为线程被挂起了,而且Android NDK不支持该方法.

I tried to kill the child thread with pthread_kill using the signals SIGTERM and SIGKILL, but it seems both are terminating my whole application and Android restarts it. I cannot use pthread_cancel because the thread is hanged and also that method is not supported on Android NDK.

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

Is there any way to kill the child thread without killing the entire app?

这是线程和启动它的代码

Here is the thread and the code starting it

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手册页中:

信号处理是整个过程的:如果信号处理程序是 安装后,处理程序将在线程 thread 中调用,但是如果 信号的处理方式是停止",继续"或终止", 此操作将影响整个过程.

Signal dispositions are process-wide: if a signal handler is installed, the handler will be invoked in the thread thread, but if the disposition of the signal is "stop", "continue", or "terminate", this action will affect the whole process.

在Dalvik中,用于特殊处理的信号(例如SIGQUIT转储堆栈,SIGUSR1导致GC)在创建任何线程之前被阻塞,然后在

In Dalvik the signals used for special handling (e.g SIGQUIT dumps the stacks, SIGUSR1 causes a GC) are blocked before any threads are created, and then unblocked in the SignalCatcher thread using sigwait(). You can't alter the block status for the threads you don't control, so this won't work for you.

您可以做的是为未使用的信号安装信号处理程序(例如,我不认为Dalvik的发行版使用SIGUSR2),并将其称为pthread_exit().如该功能的手册页所述:

What you can do instead is install a signal handler for an otherwise unused signal (e.g. I don't think SIGUSR2 is used by shipping versions of Dalvik), and have it call pthread_exit(). As noted in the man page for that function:

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

When a thread terminates, process-shared resources (e.g., mutexes, condition variables, semaphores, and file descriptors) are not released, and functions registered using atexit(3) are not called.

这听起来像是期望的"行为.

This sounds like the "desired" behavior.

说了这么多,请不要放弃不这样做的希望. :-)听起来您已经意识到问题的一部分(资源泄漏),但是您还必须考虑状态不一致的可能性,例如认为它们被退出的线程持有的互斥体.您可能最终会陷入其他线程现在会挂起或行为异常的状态.

Having said all that, please don't give up on the hope of not doing this. :-) It sounds like you recognize part of the problem (resource leaks), but you also have to consider the possibility of inconsistent state, e.g. mutexes that think they're held by the thread that exited. You can end up in a state where other threads will now hang or act strangely.

这篇关于如何在C(Android NDK)中杀死子线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆