c - 我怎样才能从那个循环之外杀死一个处于无限循环中的 pthread?

标签 c memory-leaks pthreads threadpool

我创建了一个线程并将其放入无限循环中。使用 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) 但我仍然遇到泄漏。

最佳答案

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

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

  • 确保线程在退出前不做任何需要清理的事情(例如使用malloc()分配缓冲区)
  • 确保在线程退出后,您有一些方法可以在其他地方清理线程
  • 使用pthread_cleanup_push()pthread_cleanup_pop() 添加清理处理程序以在线程被取消时清理资源。请注意,如果取消类型是异步的,这仍然存在风险,因为线程可能会在分配资源和添加清理处理程序之间被取消。
  • 避免使用 pthread_cancel() 并让线程检查一些条件以确定何时终止(这将在长时间运行的循环中检查)。由于您的线程随后会自行检查是否终止,因此它可以在检查后进行任何需要的清理工作。

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

#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()。如果线程是分离的,您不需要加入它,但您不会确切知道它何时终止(或什至大约知道,除非您添加另一种方式来指示它的退出)。

关于c - 我怎样才能从那个循环之外杀死一个处于无限循环中的 pthread?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7961029/

相关文章:

PHP - 中断或暂停 pthread 的执行

c - 无效指针再次有效

java - 如何在每次方法执行时创建(和写入)新的日志文件?

c++ - 如何解决 "Cannot Access Memory at Address c++"问题

C++:内存泄漏

algorithm - 关于任务并行化的问题

c - 通过C控制电机

c - 从程序集调用 c 函数是否需要 "asmlinkage"?

c - 如何获得复杂的 C 预处理器行为以简化动态程序汇编

objective-c - 为什么在多个线程内修改NSMutableSet时崩溃,但是在同一线程内修改自定义对象Person却不会崩溃?