gcc (GCC) 4.6.3
valgrind-3.6.1
我创建了一个应用程序,它在2个不同的线程中发送和接收一些消息,用于发送和接收。使用pthreads,条件变量和互斥锁来锁定。
然而,发送方将发送消息,然后通知接收方接收消息并进行处理。它在while循环中执行此操作。
但是,如果我想使用ctrl-c退出应用程序并处理中断,则会出现问题。如果没有发送消息,则接收器卡在等待接收的while循环中。
主线程将调用join并阻塞等待接收器完成。但它没有等待pthread_cond_wait
。
我在考虑使用pthread_cancel
或pthread_kill
。但我不喜欢这样做,因为它不允许线程正常退出。
主要功能
void main(void)
{
/* Do some stuff here */
/* Start thread that will send a message */
if(pthread_create(&thread_recv_id, &thread_attr, thread_recv_fd, NULL) == -1) {
fprintf(stderr, "Failed to create thread, reason [ %s ]",
strerror(errno));
break;
}
printf("Start listening for receiving data'\n");
/* Start thread to receive messages */
if(pthread_create(&thread_send_id, &thread_attr, thread_send_fd, NULL) == -1) {
fprintf(stderr, "Failed to create thread for receiving, reason [ %s ]",
strerror(errno));
break;
}
/* Clean up threading properties */
pthread_join(thread_send_id, NULL);
pthread_join(thread_recv_id, NULL); <---- blocking here waiting for the recv thread to finish
pthread_mutex_destroy(&mutex_queue);
pthread_cond_destroy(&cond_queue);
return 0;
}
发件人帖子
void *thread_send_fd()
{
pthread_mutex_lock(&mutex_queue);
if(send_fd((int)fd) == FALSE) {
/* Just continue to send another item */
continue;
}
/* Signal the waiting thread to remove the item that has been sent */
pthread_cond_signal(&cond_queue);
pthread_mutex_unlock(&mutex_queue);
}
收件人帖子
void *thread_recv_fd()
{
while(is_receiving()) {
pthread_mutex_lock(&mutex_queue);
/* Wait for an item to be sent on the queue */
pthread_cond_wait(&cond_queue, &mutex_queue); <---- waiting here
queue_remove();
pthread_mutex_unlock(&mutex_queue);
}
pthread_exit(NULL);
}
答案 0 :(得分:9)
你基本上有3个选择:
使用pthread_cancel
。这将中断pthread_cond_wait
调用,然后退出线程,在上升过程中调用注册了pthread_cleanup_push
的取消处理程序。
使用pthread_kill
向线程发送信号。这不会“杀死”线程,它只是发送一个信号。在这种情况下,您必须在该线程中为您使用的信号注册信号处理程序,并且该信号处理程序必须执行某些操作以告知线程退出。这并不比第三个选项特别好,因为信号处理程序仍然需要做一些事情来使pthread_cond_wait
循环退出。
为线程添加手动中断功能,该线程知道设置标志并发出条件变量信号。然后,pthread_cond_wait
周围的循环应该检查标志并在设置了标志时退出线程。
我会推荐(1)或(3)。使用pthread_cancel
是最通用的,但需要在线程中仔细处理,以确保有适当的pthread_cleanup_push
调用来清理线程分配的所有资源,解锁所有互斥锁等等。编写手动中断功能可能会带来更多工作,但最容易为您的应用程序量身定制。