c - pthread 条件不满足

标签 c pthreads multiprocessing

我正在创建一个永远运行的多线程应用程序,直到用户发送中断(即 CTRL+C),其中运行了output_report()方法。这是代码示例:

void output_report(int signo) {
    printf("Exiting!\n");

    pthread_mutex_lock(&mutex_num_of_threads);
    programClosing = true;
    while (numOfThreads != 0){
       pthread_cond_wait(&allThreadsCompleteCond, &mutex_num_of_threads);
    } 
    pthread_mutex_unlock(&mutex_num_of_threads);

    printf("Closing Now!\n"); //This part is not reached

    pthread_exit(NULL); // Is this needed?
    exit(0);
}

void dispatch(struct pcap_pkthdr *header, const unsigned char *packet,
        int verbose) {

    static bool thread_settings_initialised = false;

    //Only run the first time dispatch method runs
    if (thread_settings_initialised == false){
        thread_settings_initialised = true;

        if (signal(SIGINT, output_report) == SIG_ERR)
             fprintf(stderr, "\ncan't catch SIGINT\n");

        //...    

        //Set mutex for the appropriate variables to remain thread safe
        pthread_mutex_init( &mutex_num_of_threads, NULL);
        //...

        //Set attr so threads are "Detached"
        pthread_attr_init(&attr);
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

        //Set pthread_cond_init
        pthread_cond_init(&allThreadsCompleteCond, NULL);
    }

    //...

    pthread_mutex_lock(&mutex_num_of_threads);
    numOfThreads++;
    pthread_mutex_unlock(&mutex_num_of_threads);


    //...
    int rc = pthread_create( &tid, &attr, analyse, (void *) &data);
    //...
}

void analyse(void *thread_data) {
    //...

    pthread_mutex_lock(&mutex_num_of_threads);
    numOfThreads--;
    if (programClosing == true && numOfThreads == 0) {
       pthread_cond_signal(&allThreadsCompleteCond);
    }
    pthread_mutex_unlock(&mutex_num_of_threads);

    pthread_exit(NULL);
}

我的问题是,每当我使用 CTRL+C 时,程序就会停止(不是完全退出,因为程序仍在运行。我必须使用 CTRL+z 才能退出)。程序输出“Exiting”,但不是“Closing now”,这意味着未满足“allThreadsCompleteCond”,但我不确定为什么。

更新

感谢 Paul Griffiths 的回答,我更新了我的代码,如下所示:

void exitHandler(int signum){
    programClosing = 1;
}

void output_report(int signo) {
    while (programClosing == 1){
        printf("Exiting!\n");
        //rest same as before
        exit(0)
    }
}

void dispatch(struct pcap_pkthdr *header, const unsigned char *packet,
        int verbose) {

    static bool thread_settings_initialised = false;
    int rc;

    printf("DISPATCH!\n");
    //Only run the first time dispatch method runs
    if (thread_settings_initialised == false){
        thread_settings_initialised = true;

        //Set mutex for the appropriate variables to remain thread safe
        //..

        //Set attr so threads are "Detached"
        //..

        //...

        if (signal(SIGINT, exitHandler) == SIG_ERR)
            fprintf(stderr, "\ncan't catch SIGINT\n");

        pthread_t exit_tid;
        rc = pthread_create( &exit_tid, &attr, output_report, (void *) NULL);
        if (rc) {
            printf("ERROR; return code from pthread_create() is %d\n", rc);
            exit(-1);
        }

    }

    //...
    ///same as before

}

现在更新后的代码仍然没有输出文本“Exiting”!

最佳答案

printf(),特别是这里的 pthread_mutex_lock()pthread_cond_wait()pthread_mutex_unlock() > 从信号处理程序调用通常不安全。你所看到的行为就是证明。有时这样做是可以的,但要实现这一目标需要确保程序的其余部分不会因此而受到不利影响,这对于重要的程序来说通常是不可行的。

信号处理一开始就很棘手,而且一般来说,混合线程和信号会使事情变得更加棘手。一般方法是(1)仅从信号处理程序调用异步信号安全的函数(您可以找到它们的列表 here ); (2) 在信号处理程序中做尽可能少的工作。此外,您还经常需要考虑 (3) 阻止信号或关键部分的某些信号的传递,在这些部分中,您不希望一组操作被信号中断,而该信号的处理程序可能会对这些操作产生不利干扰。

信号处理程序可以安全地写入 volatile sig_atomic_t类型的变量,因此常见的策略是让信号处理程序只设置这样一个变量,然后主程序定期检查该变量。例如:

volatile sig_atomic_t im_done = 0;

void handler(int signum)
{
    im_done = 1;
}

int main(void)
{
    /*  Do init stuff and register your signal handler  */

    while ( !im_done ) {

       /*  Do your main work here  */

    }

    /*  Clean up and get ready to exit here  */

    return 0;
}

关于c - pthread 条件不满足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27327196/

相关文章:

c - 使用可调整大小的数组初始化列表结构的正确方法

java - 这是一个好习惯吗? "/*/something/*/something//*/"

c - gcc 原子读写

c - 使用 Struct 将字符串数组和索引传递给 C 中的线程

c - 试图理解 pthread_cond_lock 和 pthread_cond_signal

linux - 同步shell脚本执行

python - Django:多处理中的查询发生 django.db.utils.OperationalError:SSL 错误?

python - 在Python中在另一个类中创建代理类

c - 在 C 中使用 OpenSSL 加密字符串

linux - pthread_rwlock_t 跨进程 : Repair after crash?