“pthread_join”不会在刚刚取消的线程上返回(使用“pthread_cancel”)

加兰

我的程序中有一个线程池(QueueWorkers类),它们使用以下逻辑释放:

int QueueWorkers::stop()
{
  for (unsigned int ix = 0; ix < threadIds.size(); ++ix)
  {
    pthread_cancel(threadIds[ix]);
    pthread_join(threadIds[ix], NULL);
  }

  return 0;
}

其中threadIds是类型为 的类变量std::vector<pthread_t>

这个逻辑在大多数情况下都有效,但我已经检查过它有一定概率失败的测试。特别是有时在下一行pthread_cancelpthread_join语句执行后永远不会返回并且我的程序挂起。

据我所知,到目前为止,pthread_join在取消的线程上使用应该总是返回。是否有任何情况可以避免这种情况或以任何方式调试这里发生的事情?我在终止时释放线程的方法是否正确?

附加信息:线程有一个取消处理程序(使用 注册pthread_cleanup_push),它释放线程使用的动态内存以避免泄漏。在正常情况下,处理程序被调用pthread_cancel并且工作正常,但时间pthread_join失败返回我检查过取消处理程序没有被调用。

提前致谢!

编辑:正如问题评论中所建议的,我修改了我的代码以检查pthread_cancel. 无论之后是否pthread_join按预期工作,它始终为 0

EDIT2:根据对此问题的一些评论的要求,让我提供有关其工作原理的更多详细信息。

线程池由以下start()方法初始化

int QueueWorkers::start()
{
  // numberOfThreads and pQueue are class variables
  for (int i = 0; i < numberOfThreads; ++i)
  {
    pthread_t  tid;
    pthread_create(&tid, NULL, workerFunc, pQueue);  
    threadIds.push_back(tid);
  }

  return 0;
}

启动函数workerFunc()如下(简化):

static void* workerFunc(void* pQueue)
{
  // Initialize some dynamic objects (Foo for simplification)
  Foo* foo = initFoo();

  // Set pthread_cancel handler
  pthread_cleanup_push(workerFinishes, foo);

  // Loop forever
  for (;;)
  {
    // Wait for new item to process on pQueue
    ... paramsV = ((Queue*) pQueue)->pop();

    // Then process it
    ...
  }

  // Next statemement never executes but compilation breaks without it. See this note in pthread.h:
  // "pthread_cleanup_push and pthread_cleanup_pop are macros and must always be used in
  // matching pairs at the same nesting level of braces".
  pthread_cleanup_pop(0);
}

请注意pthread_cleanup_push()启动以太网循环之前语句。这样做是为了在取消Foo对象时实现清理逻辑

static void workerFinishes(void* curl)
{
  freeFoo((Foo*) curl);
}

我希望没有过度简化代码。无论如何,您可以在此处查看原始版本

杂七杂八

确定线程处于取消状态还是您的线程cancelation_type是异步的?

manpthread_cancel

线程的取消类型由 pthread_setcanceltype(3) 确定,可以是异步的或延迟的(新线程的默认设置)。异步可取消性意味着线程可以随时取消(通常是立即取消,但系统不保证这一点)。延迟可取消性意味着取消将被延迟,直到线程下一次调用作为取消点的函数。pthreads(7) 中提供了是或可能是取消点的函数列表。

我不认为取消线程是确保线程完成的最佳方法。也许您可以向线程发送一条消息,它应该停止并确保线程确实收到消息并会处理它。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

使用pthread_cancel取消线程:好的做法还是不好的

在示例的x64窗口上,崩溃在pthread_cancel和pthread_join上

pthread_cancel()不会像应有的那样取消线程

pthread_cancel和取消点

为什么pthread_join不会阻塞并等待线程完成?

在线程执行IO时,pthread_cancel会取消线程吗?

使用pthread_join的pthread的同步问题

如何不使用pthread_join()同步线程?

pthread_cancel()并使用清除处理程序。

从 pthread_join 返回时出现 segFault

线程可以通过调用 pthread_cancel 来自毁吗

如何通过使用pthread_cancel避免内存泄漏?

使用互斥量条件变量时的pthread_cancel

分段错误加入线程号5(pthread_join)

函数pthread_join的代码-Pthread库

如何实现pthread_join?

在pthread_join()中阻塞

使用MySQLi fetch的PHP不会在LEFT JOIN上返回带有NULL的行

pthread_join返回一个NULL地址

带返回值的pthread_join给出分段错误

pthread_cancel之后的分段错误

关于线程的pthread_join()和pthread_detach()的“回收存储”是什么意思?

我可以在pthread_detached线程上调用pthread_join吗?

pthread_cancel()是否可能终止另一个意外线程?

在C中使用pthread_join时出现分段错误

在Linux中何时使用pthread_exit()和何时使用pthread_join()?

linux 上的 pthread_cancel() 导致异常/核心转储,为什么?

pthread_join 导致奇怪的执行顺序

pthread_join free():无效的指针错误