如何从该循环之外杀死处于无限循环中的 pthread? [英] How can I kill a pthread that is in an infinite loop, from outside that loop?

查看:19
本文介绍了如何从该循环之外杀死处于无限循环中的 pthread?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个线程并将其放入一个无限循环中.使用 valgrind 检查代码时出现内存泄漏.这是我的代码:

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

所以在 main 中创建了一个线程,并且一直运行 thread_do().有没有办法在 2 秒后从 main 内部杀死它?我已经尝试了 pthread_detach(th)pthread_cancel(th) 但我仍然有泄漏.

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.

推荐答案

正如@sarnold 所指出的,默认情况下,您的线程不能使用 pthread_cancel() 取消而不调用任何取消的函数点...但这可以通过使用 pthread_setcanceltype() 将线程的取消类型设置为异步而不是延迟来更改.为此,在开始循环之前,您需要在线程函数的开头附近添加类似 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); 的内容.然后,您可以通过从 main() 调用 pthread_cancel(th) 来终止线程.

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 using pthread_setcanceltype() to set the thread's cancellation type to asynchronous instead of deferred. To do that, you'd add something like pthread_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 calling pthread_cancel(th) from main().

但是请注意,以这种方式取消线程(无论是否异步)不会清除线程函数中分配的任何资源(正如 Kevin 在评论中指出的那样).为了干净利落地做到这一点,您可以:

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() 分配缓冲区)
  • 确保在线程退出后,在其他地方的线程之后,您有某种清理方法
  • 使用pthread_cleanup_push()pthread_cleanup_pop() 添加清理处理程序以在线程被取消时清理资源.请注意,如果取消类型是异步的,这仍然存在风险,因为在分配资源和添加清理处理程序之间可能会取消线程.
  • 避免使用 pthread_cancel() 并让线程检查某些条件以确定何时终止(这将在长时间运行的循环中检查).由于您的线程随后会自行检查终止情况,因此它可以在检查后执行所需的任何清理工作.
  • Ensure that the thread doesn't do anything it needs to clean up before exit (e.g. using malloc() to allocate a buffer)
  • Ensure that you have some way of cleaning up after the thread elsewhere, after the thread exits
  • Use pthread_cleanup_push() and pthread_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.
  • Avoid using 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.

实现最后一个选项的一种方法是使用互斥锁作为标志,并使用 pthread_mutex_trylock() 包裹在一个函数中进行测试以在循环测试中使用:

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:

#include <pthread.h>
#include <unistd.h>
#include <errno.h>

/* Returns 1 (true) if the mutex is unlocked, which is the
 * thread's signal to terminate. 
 */
int needQuit(pthread_mutex_t *mtx)
{
  switch(pthread_mutex_trylock(mtx)) {
    case 0: /* if we got the lock, unlock and return 1 (true) */
      pthread_mutex_unlock(mtx);
      return 1;
    case EBUSY: /* return 0 (false) if the mutex was locked */
      return 0;
  }
  return 1;
}

/* Thread function, containing a loop that's infinite except that it checks for
 * termination with needQuit() 
 */
void *thread_do(void *arg)
{
  pthread_mutex_t *mx = arg;
  while( !needQuit(mx) ) {}
  return NULL;
}

int main(int argc, char *argv[])
{
  pthread_t th;
  pthread_mutex_t mxq; /* mutex used as quit flag */

  /* init and lock the mutex before creating the thread.  As long as the
     mutex stays locked, the thread should keep running.  A pointer to the
     mutex is passed as the argument to the thread function. */
  pthread_mutex_init(&mxq,NULL);
  pthread_mutex_lock(&mxq);
  pthread_create(&th,NULL,thread_do,&mxq);

  sleep(2);

  /* unlock mxq to tell the thread to terminate, then join the thread */
  pthread_mutex_unlock(&mxq); 
  pthread_join(th,NULL);

  sleep(2);
  return 0;
}

如果线程没有被分离(通常不是默认的),你应该在线程停止后调用pthread_join().如果线程是分离的,您不需要加入它,但您不会确切知道它何时终止(甚至大约,除非您添加另一种方式来指示其退出).

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).

这篇关于如何从该循环之外杀死处于无限循环中的 pthread?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆