退出清理线程
Posted
技术标签:
【中文标题】退出清理线程【英文标题】:thread at exit cleanup 【发布时间】:2012-10-01 09:17:11 【问题描述】:我有一个应用程序,其中我有 1 个主线程,它创建 10 个不同的线程来完成某些工作。在应用程序结束时,当我尝试退出时,应用程序无法干净地退出。堆栈跟踪不是那么有用,但它显示函数“cancel_deliver()”中的崩溃我的第一个猜测是这是在释放每个线程使用的资源时进行的一些底层调用,但并不完全确定。
fyi:每个线程的回调函数都有一个while(1)循环:
这里是sn-p
void main (...)
pthread_t tid;
for (int i=0; i<10; i++)
pthread_create(&tid, NULL, xyzCallback, NULL);
void xyzCallback(void* data)
while (1)
////
void atExit()
exit(1);
我可以做些什么来释放我的线程使用的资源并干净地退出?
【问题讨论】:
加入你的话题! 向我们展示cancel_deliver
的代码。
据我所知,您不必加入。使用 exit() 退出应该没问题。我的猜测是问题出在其他地方。线程有什么作用?你的目标是什么平台?不过,如果您可以退出线程,例如通过从回调返回,看看问题是否消失会很有趣。
堆栈跟踪显示 ._cancel_deliver 正在从 pthread_self(..) 调用,生成线程中的处理完全独立于主线程。这目前正在 AIX 平台上发生。
【参考方案1】:
对于这种情况
如果我正确理解您的设置...
您可以做的一件事是拥有一组“标志”变量,每个线程(包括主线程)一个。当主线程准备好结束时,设置它的标志。应在其他 10 个线程中不断检查此标志。一旦它被设置,更改该特定线程的标志变量并调用pthread_exit
。在主退出方法中,只有在设置了所有标志变量后才终止。
假设您的程序没有因为其他原因而崩溃,这应该使所有线程能够以受控方式完成。
(或在主退出函数中使用pthread_join
,因为pthread_exit
返回pthread_join
使用的信息)
一般情况
使用pthread_exit
而不是exit(1)
干净地退出线程。
来自LLNL POSIX 线程编程页面:
如果你没有显式调用 pthread_exit(),那么如果 main() 在它产生的线程之前完成,就会出现一个明确的问题。它创建的所有线程都将终止,因为 main() 已完成并且不再存在以支持线程。
另见 pthread_exit man page。
【讨论】:
来自pthreads_create man page"新线程以下列方式之一终止: ... 进程中的任何线程调用exit(3),或者主线程执行一个从 main() 返回。这会导致进程中的所有线程终止。”但这取决于线程在做什么,因为这可能会导致崩溃。 atExit() 函数中的 pthread_exit() 将干净地退出主线程,但是如何为每个生成的线程调用 pthread_exit()。通常,它应该从 threadCallback 函数中调用。就我而言,我有一个 while(1) 循环,所以这无济于事。无论如何,我仍然可以为主线程插入 pthread_exit。应该不会疼的。 同意。不寻常的 pthread 应用程序...通常您有线程自行退出并将终止信息返回给 main。【参考方案2】:您需要决定您的线程 (1) 是否需要以明确定义的方式(状态)结束,或者后者是否无关紧要 (2) 注意何时何地可以取消它们(当程序结束)
引用 1:一种可能的方法是实现一个退出条件,当程序终止并让线程离开其while(1)
循环时将触发该退出条件。在离开 main
循环调用 pthread_join()
之前,它通过调用 pthread_create()
接收到任何 pthread_t pthread
。如果所有线程都终止了 main
的连接循环,则 main 结束,所有线程都已终止。
引用 2:这是更关键的情况,因为根据线程函数的代码,不清楚它将在哪里取消,这可能会导致意外行为。可以在所谓的取消点取消线程。 Some system calls are treated as such。
在任何情况下,线程函数确实不一定需要调用pthread_exit()
作为最后一条语句。仅当您希望 pthread_join()
接收传递给 pthread_exit()
的指针时才需要这样做。
【讨论】:
以上是关于退出清理线程的主要内容,如果未能解决你的问题,请参考以下文章