我正在创建一个永久运行的多线程应用程序,直到用户发送中断(即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来摆脱它)。程序输出“退出”但不输出“立即关闭”意味着“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
}
现在更新的代码仍然没有输出文本“退出”!
答案 0 :(得分:1)
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;
}