POSIX 标准对 atexit() 处理程序中的线程堆栈有何规定?操作系统的做法是什么?

2024-04-07

当我们的 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(使用前将#替换为@)

POSIX 标准对 atexit() 处理程序中的线程堆栈有何规定?操作系统的做法是什么? 的相关文章

随机推荐