如何从循环外部杀死处于无限循环中的 pthread?
我创建一个线程并将其放入无限循环中。使用 valgrind 检查代码时出现内存泄漏。这是我的代码:
#include <pthread.h>
#include <time.h>
void thread_do(void){
while(1){}
}
int main(){
pthread_t th;
pthread_create(&th, NULL, (void *)thread_do, NULL);
sleep(2);
/* I want to kill thread here */
sleep(2);
return 0;
}
因此,在 main 中创建了一个线程,并且始终运行 thread_do() 。有没有办法在 2 秒后从 main 内部杀死它?我已经尝试了 pthread_detach(th) 和 pthread_cancel(th) 但仍然出现泄漏。
I create a thread and I put it into an infinite loop. I get memory leaks when checking the code with valgrind. Here is my code:
#include <pthread.h>
#include <time.h>
void thread_do(void){
while(1){}
}
int main(){
pthread_t th;
pthread_create(&th, NULL, (void *)thread_do, NULL);
sleep(2);
/* I want to kill thread here */
sleep(2);
return 0;
}
So a thread is created in main and just runs thread_do() all the time. Is there a way to kill it from inside main after 2 seconds? I have tried both pthread_detach(th)
and pthread_cancel(th)
but I still get leaks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
正如 @sarnold 指出的那样,默认情况下,如果不调用任何作为取消点的函数,则无法使用 pthread_cancel() 取消线程...但这可以通过使用 pthread_setcanceltype() 来更改 将线程的取消类型设置为异步而不是延迟。为此,您需要在启动循环之前在线程函数的开头附近添加类似
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
的内容。然后,您可以通过从main()
调用pthread_cancel(th)
来终止线程。但请注意,以这种方式取消线程(无论是否异步)不会清除线程函数中分配的任何资源(如 Kevin 在评论中所述)。为了干净地做到这一点,您可以:
malloc()
分配缓冲区)pthread_cleanup_push()
和pthread_cleanup_pop()
添加清理处理程序以在线程取消时清理资源。请注意,如果取消类型是异步的,这仍然存在风险,因为线程可能会在分配资源和添加清理处理程序之间被取消。实现最后一个选项的一种方法是使用互斥体作为标志,并使用包含在循环测试中使用的函数中的
pthread_mutex_trylock()
对其进行测试:如果线程未分离(通常默认情况下不是),您应该在停止线程后调用
pthread_join()
。如果线程已分离,则不需要加入它,但您将不知道它何时终止(甚至不知道它何时终止,除非您添加另一种方式来指示其退出)。As @sarnold pointed out, by default your thread can't be cancelled with
pthread_cancel()
without calling any functions that are cancellation points... but this can be changed by usingpthread_setcanceltype()
to set the thread's cancellation type to asynchronous instead of deferred. To do that, you'd add something likepthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
near the start of your thread function, before you start the loop. You would then be able to terminate the thread by callingpthread_cancel(th)
frommain()
.Note, though, that cancelling threads this way (whether asynchronous or not) doesn't clean up any resources allocated in the thread function (as noted by Kevin in a comment). In order to do this cleanly, you can:
malloc()
to allocate a buffer)pthread_cleanup_push()
andpthread_cleanup_pop()
to add cleanup handlers to clean up resources when the thread is cancelled. Note that this is still risky if the cancellation type is asynchronous, because the thread could be cancelled between allocating a resource and adding the cleanup handler.pthread_cancel()
and have the thread check some condition to determine when to terminate (which would be checked in long-running loops). Since your thread then checks for termination itself, it can do whatever cleanup it needs to after the check.One way of implementing the last option is to use a mutex as a flag, and test it with
pthread_mutex_trylock()
wrapped in a function to use in the loop tests:If the thread is not detached (it generally isn't by default), you should call
pthread_join()
after stopping the thread. If the thread is detached, you don't need to join it, but you won't know exactly when it terminates (or even approximately, unless you add another way to indicate its exit).一些小想法:
thread_do()
将永远不会被取消,因为它永远不会调用任何函数是取消点:pthread_join(3)
:A few small thoughts:
thread_do()
will never be canceled, because it never calls any functions that are cancellation points:pthread_join(3)
before the end of your program: