pthread条件不被满足

问题描述:

我正在创建一个多线程应用程序,该应用程序永远运行,直到用户发送中断(即CTRL + C),其中运行output_report()方法。下面是代码的样本:pthread条件不被满足

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摆脱它)。该程序输出“退出”,但不是“现在关闭”意味着“allThreadsCompleteCond”没有被满足,但我不知道为什么。

UPDATE

感谢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 

} 

现在更新的代码仍然甚至不输出文本 “退出”!

+1

'的printf()','pthread_mutex_lock()的','调用pthread_cond_wait()'和'调用pthread_mutex_unlock()'是不是安全,从信号处理程序调用。你所看到的行为就是这方面的证据。你需要重新思考你的策略。 – 2014-12-06 01:33:54

+0

最新的替代方案 – 2014-12-06 01:34:19

+1

很可能让信号处理程序不做任何事情,而是设置一个类型为'sig_atomic_t'的状态变量,并且让单个线程定期检查它,并在其他线程关闭时关闭其他线程。一般来说,混合线程和信号会导致很多类似的问题。 – 2014-12-06 01:38:50

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; 
} 
+0

你的新代码似乎并没有在任何地方调用'output_report()',所以显然你永远不会看到'printf(“Exiting!\ n”)的效果;''output_report()'本身看起来仍然是写入的成为一个信号处理程序,这不是你想要的。 – 2014-12-06 02:43:27

+0

对不起,我写错了,但结果相同。它仍然没有工作!\t \t printf(“退出!\ n”);不敢跑! – 2014-12-06 03:15:35

+0

好的,你需要坐下来思考它,基本上设计并调试你的程序。在这里发布一些小片段,并说它不起作用不会使它开始工作。 – 2014-12-06 03:17:20