当我们的 UNIX/C 程序需要紧急退出时,我们使用 exit(3) 函数并安装 atexit(3) 处理程序来进行紧急清理。这种方法工作得很好,直到我们的应用程序被线程化,此时 atexit() 处理程序停止正常工作。
我们通过试验了解到一个错误,线程可能已经在 atexit() 处理程序中死亡,并且它们的堆栈被释放。
我未能在标准链接线程消失与atexit()中找到引用:从main()返回后线程不再存在,但它是在调用atexit()之前还是之后? Linux、FreeBSD 和 Mac 上的实际做法是什么?
多线程程序中是否有一个好的紧急清理模式?
POSIX标准
Posix 似乎没有定义是否atexit
处理程序在线程终止之前或之后调用exit
.
进程有两种(或三种)方式“正常”终止。
所有线程终止。当最后一个线程退出时,通过返回或调用pthread_exit
, atexit
处理程序已运行。在这种情况下,没有其他线程。 (这是与平台相关的。如果主线程终止而不是通过其他方式终止,某些平台可能会终止其他线程exit
,其他则不然)。
一个线程调用exit
。在这种情况下,atexit
处理程序将运行并终止所有线程。 Posix 没有指定顺序。
main
返回。这或多或少相当于调用exit()
作为最后一行main
,所以可以按上面的方法处理。
操作系统实践
在 Linux 中,文档https://linux.die.net/man/2/exit https://linux.die.net/man/2/exit说线程被终止_exit
呼叫exit_group
, 然后_exit
之后被调用atexit
处理程序。因此在Linux中调用exit
any atexit
处理程序在线程终止之前运行。请注意,它们在调用的线程上运行exit
,不是调用的线程atexit
.
如果您关心的话,在 Windows 上,行为是相同的。
紧急清理模式。
最好的模式是:切勿处于需要紧急清理的状态。
-
无法保证您的清理工作会运行因为
你可以有一个
kill -9
或者
停电。
- 因此,您需要能够在这种情况下恢复。
- 如果你能从那个中恢复过来,你也可以从
abort
,所以你可以使用abort
用于您的紧急出口。
如果你做不到这一点,或者你想做一些“最好有”的清理工作,atexit
处理程序应该没问题provided您首先要优雅地停止进程中的所有线程,以防止在进行清理时进入不一致的状态。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)